]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix some bugs in the HLSL shader, mostly to do with r_shadow_deferred
[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 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1837 "       temp.yz -= floor(temp.yz);\n"
1838 "       gl_FragColor = temp;\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 float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\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.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2496 "       VectorR.w = gl_Position.z;\n"
2497 "}\n"
2498 "#endif // VERTEX_SHADER\n"
2499 "\n"
2500 "#ifdef FRAGMENT_SHADER\n"
2501 "void main\n"
2502 "(\n"
2503 "float4 TexCoordBoth : TEXCOORD0,\n"
2504 "float3 EyeVector : TEXCOORD2,\n"
2505 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2506 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2507 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2508 "uniform sampler Texture_Normal : register(s0),\n"
2509 "#ifdef USEALPHAKILL\n"
2510 "uniform sampler Texture_Color : register(s1),\n"
2511 "#endif\n"
2512 "uniform sampler Texture_Gloss : register(s2),\n"
2513 "#ifdef USEVERTEXTEXTUREBLEND\n"
2514 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2515 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2516 "#endif\n"
2517 "#ifdef USEOFFSETMAPPING\n"
2518 "uniform float OffsetMapping_Scale : register(c24),\n"
2519 "#endif\n"
2520 "uniform half SpecularPower : register(c36),\n"
2521 "#ifdef HLSL\n"
2522 "out float4 gl_FragData0 : COLOR0,\n"
2523 "out float4 gl_FragData1 : COLOR1\n"
2524 "#else\n"
2525 "out float4 gl_FragColor : COLOR\n"
2526 "#endif\n"
2527 ")\n"
2528 "{\n"
2529 "       float2 TexCoord = TexCoordBoth.xy;\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "       // apply offsetmapping\n"
2532 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2533 "#define TexCoord TexCoordOffset\n"
2534 "#endif\n"
2535 "\n"
2536 "#ifdef USEALPHAKILL\n"
2537 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2538 "               discard;\n"
2539 "#endif\n"
2540 "\n"
2541 "#ifdef USEVERTEXTEXTUREBLEND\n"
2542 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2543 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2544 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2545 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2546 "#endif\n"
2547 "\n"
2548 "#ifdef USEVERTEXTEXTUREBLEND\n"
2549 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2550 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2551 "#else\n"
2552 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2553 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2554 "#endif\n"
2555 "\n"
2556 "#ifdef HLSL\n"
2557 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2558 "       float Depth = VectorR.w / 256.0;\n"
2559 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2560 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2561 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2562 "       gl_FragData1 = depthcolor;\n"
2563 "#else\n"
2564 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2565 "#endif\n"
2566 "}\n"
2567 "#endif // FRAGMENT_SHADER\n"
2568 "#else // !MODE_DEFERREDGEOMETRY\n"
2569 "\n"
2570 "\n"
2571 "\n"
2572 "\n"
2573 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2574 "#ifdef VERTEX_SHADER\n"
2575 "void main\n"
2576 "(\n"
2577 "float4 gl_Vertex : POSITION,\n"
2578 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2579 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2580 "out float4 gl_Position : POSITION,\n"
2581 "out float4 ModelViewPosition : TEXCOORD0\n"
2582 ")\n"
2583 "{\n"
2584 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2585 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2586 "}\n"
2587 "#endif // VERTEX_SHADER\n"
2588 "\n"
2589 "#ifdef FRAGMENT_SHADER\n"
2590 "void main\n"
2591 "(\n"
2592 "#ifdef HLSL\n"
2593 "float2 Pixel : VPOS,\n"
2594 "#else\n"
2595 "float2 Pixel : WPOS,\n"
2596 "#endif\n"
2597 "float4 ModelViewPosition : TEXCOORD0,\n"
2598 "uniform float4x4 ViewToLight : register(c44),\n"
2599 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2600 "uniform float3 LightPosition : register(c23),\n"
2601 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2602 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2603 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2604 "#ifdef USESPECULAR\n"
2605 "uniform half3 DeferredColor_Specular : register(c11),\n"
2606 "uniform half SpecularPower : register(c36),\n"
2607 "#endif\n"
2608 "uniform sampler Texture_Attenuation : register(s9),\n"
2609 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2610 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2611 "\n"
2612 "#ifdef USECUBEFILTER\n"
2613 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2614 "#endif\n"
2615 "\n"
2616 "#ifdef USESHADOWMAP2D\n"
2617 "# ifdef USESHADOWSAMPLER\n"
2618 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2619 "# else\n"
2620 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2621 "# endif\n"
2622 "#endif\n"
2623 "\n"
2624 "#ifdef USESHADOWMAPVSDCT\n"
2625 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2626 "#endif\n"
2627 "\n"
2628 "#if defined(USESHADOWMAP2D)\n"
2629 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2630 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2631 "#endif\n"
2632 "\n"
2633 "out float4 gl_FragData0 : COLOR0,\n"
2634 "out float4 gl_FragData1 : COLOR1\n"
2635 ")\n"
2636 "{\n"
2637 "       // calculate viewspace pixel position\n"
2638 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2639 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2640 "       float3 position;\n"
2641 "#ifdef HLSL\n"
2642 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2643 "#else\n"
2644 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2645 "#endif\n"
2646 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2647 "       // decode viewspace pixel normal\n"
2648 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2649 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2650 "       // surfacenormal = pixel normal in viewspace\n"
2651 "       // LightVector = pixel to light in viewspace\n"
2652 "       // CubeVector = position in lightspace\n"
2653 "       // eyevector = pixel to view in viewspace\n"
2654 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2655 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2656 "#ifdef USEDIFFUSE\n"
2657 "       // calculate diffuse shading\n"
2658 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2659 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2660 "#endif\n"
2661 "#ifdef USESPECULAR\n"
2662 "       // calculate directional shading\n"
2663 "       float3 eyevector = position * -1.0;\n"
2664 "#  ifdef USEEXACTSPECULARMATH\n"
2665 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2666 "#  else\n"
2667 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2668 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2669 "#  endif\n"
2670 "#endif\n"
2671 "\n"
2672 "#if defined(USESHADOWMAP2D)\n"
2673 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2674 "#ifdef USESHADOWMAPVSDCT\n"
2675 ", Texture_CubeProjection\n"
2676 "#endif\n"
2677 "       ));\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USEDIFFUSE\n"
2681 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2682 "#else\n"
2683 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2684 "#endif\n"
2685 "#ifdef USESPECULAR\n"
2686 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2687 "#else\n"
2688 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2689 "#endif\n"
2690 "\n"
2691 "# ifdef USECUBEFILTER\n"
2692 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2693 "       gl_FragData0.rgb *= cubecolor;\n"
2694 "       gl_FragData1.rgb *= cubecolor;\n"
2695 "# endif\n"
2696 "}\n"
2697 "#endif // FRAGMENT_SHADER\n"
2698 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2699 "\n"
2700 "\n"
2701 "\n"
2702 "\n"
2703 "#ifdef VERTEX_SHADER\n"
2704 "void main\n"
2705 "(\n"
2706 "float4 gl_Vertex : POSITION,\n"
2707 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2708 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2709 "float4 gl_Color : COLOR0,\n"
2710 "#endif\n"
2711 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2712 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2713 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2714 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2715 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2716 "\n"
2717 "uniform float3 EyePosition : register(c24),\n"
2718 "uniform float4x4 TexMatrix : register(c0),\n"
2719 "#ifdef USEVERTEXTEXTUREBLEND\n"
2720 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2721 "#endif\n"
2722 "#ifdef MODE_LIGHTSOURCE\n"
2723 "uniform float4x4 ModelToLight : register(c20),\n"
2724 "#endif\n"
2725 "#ifdef MODE_LIGHTSOURCE\n"
2726 "uniform float3 LightPosition : register(c27),\n"
2727 "#endif\n"
2728 "#ifdef MODE_LIGHTDIRECTION\n"
2729 "uniform float3 LightDir : register(c26),\n"
2730 "#endif\n"
2731 "uniform float4 FogPlane : register(c25),\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "uniform float3 LightPosition : register(c27),\n"
2734 "#endif\n"
2735 "#ifdef USESHADOWMAPORTHO\n"
2736 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2737 "#endif\n"
2738 "\n"
2739 "out float4 gl_FrontColor : COLOR,\n"
2740 "out float4 TexCoordBoth : TEXCOORD0,\n"
2741 "#ifdef USELIGHTMAP\n"
2742 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2743 "#endif\n"
2744 "#ifdef USEEYEVECTOR\n"
2745 "out float3 EyeVector : TEXCOORD2,\n"
2746 "#endif\n"
2747 "#ifdef USEREFLECTION\n"
2748 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2749 "#endif\n"
2750 "#ifdef USEFOG\n"
2751 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2752 "#endif\n"
2753 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2754 "out float3 LightVector : TEXCOORD1,\n"
2755 "#endif\n"
2756 "#ifdef MODE_LIGHTSOURCE\n"
2757 "out float3 CubeVector : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2760 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2761 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2762 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2763 "#endif\n"
2764 "#ifdef USESHADOWMAPORTHO\n"
2765 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2766 "#endif\n"
2767 "out float4 gl_Position : POSITION\n"
2768 ")\n"
2769 "{\n"
2770 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2771 "#ifdef HLSL\n"
2772 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2773 "#else\n"
2774 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2775 "#endif\n"
2776 "#endif\n"
2777 "       // copy the surface texcoord\n"
2778 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2779 "#ifdef USEVERTEXTEXTUREBLEND\n"
2780 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2781 "#endif\n"
2782 "#ifdef USELIGHTMAP\n"
2783 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2784 "#endif\n"
2785 "\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "       // transform vertex position into light attenuation/cubemap space\n"
2788 "       // (-1 to +1 across the light box)\n"
2789 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2790 "\n"
2791 "# ifdef USEDIFFUSE\n"
2792 "       // transform unnormalized light direction into tangent space\n"
2793 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2794 "       //  normalize it per pixel)\n"
2795 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2796 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2797 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2798 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2799 "# endif\n"
2800 "#endif\n"
2801 "\n"
2802 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2803 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2804 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2805 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2806 "#endif\n"
2807 "\n"
2808 "       // transform unnormalized eye direction into tangent space\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2811 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2812 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2813 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2814 "#endif\n"
2815 "\n"
2816 "#ifdef USEFOG\n"
2817 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2818 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2822 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2823 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2824 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2825 "#endif\n"
2826 "\n"
2827 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2828 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2829 "\n"
2830 "#ifdef USESHADOWMAPORTHO\n"
2831 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2832 "#endif\n"
2833 "\n"
2834 "#ifdef USEREFLECTION\n"
2835 "       ModelViewProjectionPosition = gl_Position;\n"
2836 "#endif\n"
2837 "}\n"
2838 "#endif // VERTEX_SHADER\n"
2839 "\n"
2840 "\n"
2841 "\n"
2842 "\n"
2843 "#ifdef FRAGMENT_SHADER\n"
2844 "void main\n"
2845 "(\n"
2846 "#ifdef USEDEFERREDLIGHTMAP\n"
2847 "#ifdef HLSL\n"
2848 "float2 Pixel : VPOS,\n"
2849 "#else\n"
2850 "float2 Pixel : WPOS,\n"
2851 "#endif\n"
2852 "#endif\n"
2853 "float4 gl_FrontColor : COLOR,\n"
2854 "float4 TexCoordBoth : TEXCOORD0,\n"
2855 "#ifdef USELIGHTMAP\n"
2856 "float2 TexCoordLightmap : TEXCOORD1,\n"
2857 "#endif\n"
2858 "#ifdef USEEYEVECTOR\n"
2859 "float3 EyeVector : TEXCOORD2,\n"
2860 "#endif\n"
2861 "#ifdef USEREFLECTION\n"
2862 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2863 "#endif\n"
2864 "#ifdef USEFOG\n"
2865 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2866 "#endif\n"
2867 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2868 "float3 LightVector : TEXCOORD1,\n"
2869 "#endif\n"
2870 "#ifdef MODE_LIGHTSOURCE\n"
2871 "float3 CubeVector : TEXCOORD3,\n"
2872 "#endif\n"
2873 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2874 "float4 ModelViewPosition : TEXCOORD0,\n"
2875 "#endif\n"
2876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2877 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2878 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2879 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2880 "#endif\n"
2881 "#ifdef USESHADOWMAPORTHO\n"
2882 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2883 "#endif\n"
2884 "\n"
2885 "uniform sampler Texture_Normal : register(s0),\n"
2886 "uniform sampler Texture_Color : register(s1),\n"
2887 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2888 "uniform sampler Texture_Gloss : register(s2),\n"
2889 "#endif\n"
2890 "#ifdef USEGLOW\n"
2891 "uniform sampler Texture_Glow : register(s3),\n"
2892 "#endif\n"
2893 "#ifdef USEVERTEXTEXTUREBLEND\n"
2894 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2895 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2896 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2897 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2898 "#endif\n"
2899 "#ifdef USEGLOW\n"
2900 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2901 "#endif\n"
2902 "#endif\n"
2903 "#ifdef USECOLORMAPPING\n"
2904 "uniform sampler Texture_Pants : register(s4),\n"
2905 "uniform sampler Texture_Shirt : register(s7),\n"
2906 "#endif\n"
2907 "#ifdef USEFOG\n"
2908 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2909 "uniform sampler Texture_FogMask : register(s8),\n"
2910 "#endif\n"
2911 "#ifdef USELIGHTMAP\n"
2912 "uniform sampler Texture_Lightmap : register(s9),\n"
2913 "#endif\n"
2914 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2915 "uniform sampler Texture_Deluxemap : register(s10),\n"
2916 "#endif\n"
2917 "#ifdef USEREFLECTION\n"
2918 "uniform sampler Texture_Reflection : register(s7),\n"
2919 "#endif\n"
2920 "\n"
2921 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2922 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2923 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2924 "#endif\n"
2925 "#ifdef USEDEFERREDLIGHTMAP\n"
2926 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2927 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2928 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2929 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2930 "#endif\n"
2931 "\n"
2932 "#ifdef USECOLORMAPPING\n"
2933 "uniform half3 Color_Pants : register(c7),\n"
2934 "uniform half3 Color_Shirt : register(c8),\n"
2935 "#endif\n"
2936 "#ifdef USEFOG\n"
2937 "uniform float3 FogColor : register(c16),\n"
2938 "uniform float FogRangeRecip : register(c20),\n"
2939 "uniform float FogPlaneViewDist : register(c19),\n"
2940 "uniform float FogHeightFade : register(c17),\n"
2941 "#endif\n"
2942 "\n"
2943 "#ifdef USEOFFSETMAPPING\n"
2944 "uniform float OffsetMapping_Scale : register(c24),\n"
2945 "#endif\n"
2946 "\n"
2947 "#ifdef USEDEFERREDLIGHTMAP\n"
2948 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2949 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2950 "uniform half3 DeferredMod_Specular : register(c13),\n"
2951 "#endif\n"
2952 "uniform half3 Color_Ambient : register(c3),\n"
2953 "uniform half3 Color_Diffuse : register(c4),\n"
2954 "uniform half3 Color_Specular : register(c5),\n"
2955 "uniform half SpecularPower : register(c36),\n"
2956 "#ifdef USEGLOW\n"
2957 "uniform half3 Color_Glow : register(c6),\n"
2958 "#endif\n"
2959 "uniform half Alpha : register(c0),\n"
2960 "#ifdef USEREFLECTION\n"
2961 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2962 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2963 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2964 "uniform half4 ReflectColor : register(c26),\n"
2965 "#endif\n"
2966 "#ifdef USEREFLECTCUBE\n"
2967 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2968 "uniform sampler Texture_ReflectMask : register(s5),\n"
2969 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2970 "#endif\n"
2971 "#ifdef MODE_LIGHTDIRECTION\n"
2972 "uniform half3 LightColor : register(c21),\n"
2973 "#endif\n"
2974 "#ifdef MODE_LIGHTSOURCE\n"
2975 "uniform half3 LightColor : register(c21),\n"
2976 "#endif\n"
2977 "\n"
2978 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2979 "uniform sampler Texture_Attenuation : register(s9),\n"
2980 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2984 "\n"
2985 "#ifdef USESHADOWMAP2D\n"
2986 "# ifdef USESHADOWSAMPLER\n"
2987 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2988 "# else\n"
2989 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2990 "# endif\n"
2991 "#endif\n"
2992 "\n"
2993 "#ifdef USESHADOWMAPVSDCT\n"
2994 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#if defined(USESHADOWMAP2D)\n"
2998 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2999 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3000 "#endif\n"
3001 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3002 "\n"
3003 "out float4 gl_FragColor : COLOR\n"
3004 ")\n"
3005 "{\n"
3006 "       float2 TexCoord = TexCoordBoth.xy;\n"
3007 "#ifdef USEVERTEXTEXTUREBLEND\n"
3008 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3009 "#endif\n"
3010 "#ifdef USEOFFSETMAPPING\n"
3011 "       // apply offsetmapping\n"
3012 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3013 "#define TexCoord TexCoordOffset\n"
3014 "#endif\n"
3015 "\n"
3016 "       // combine the diffuse textures (base, pants, shirt)\n"
3017 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3018 "#ifdef USEALPHAKILL\n"
3019 "       if (color.a < 0.5)\n"
3020 "               discard;\n"
3021 "#endif\n"
3022 "       color.a *= Alpha;\n"
3023 "#ifdef USECOLORMAPPING\n"
3024 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3025 "#endif\n"
3026 "#ifdef USEVERTEXTEXTUREBLEND\n"
3027 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3028 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3029 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3030 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3031 "       color.a = 1.0;\n"
3032 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3033 "#endif\n"
3034 "\n"
3035 "       // get the surface normal\n"
3036 "#ifdef USEVERTEXTEXTUREBLEND\n"
3037 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3038 "#else\n"
3039 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3040 "#endif\n"
3041 "\n"
3042 "       // get the material colors\n"
3043 "       half3 diffusetex = color.rgb;\n"
3044 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3045 "# ifdef USEVERTEXTEXTUREBLEND\n"
3046 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3047 "# else\n"
3048 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3049 "# endif\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEREFLECTCUBE\n"
3053 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3054 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3055 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3056 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3057 "#endif\n"
3058 "\n"
3059 "\n"
3060 "\n"
3061 "\n"
3062 "#ifdef MODE_LIGHTSOURCE\n"
3063 "       // light source\n"
3064 "#ifdef USEDIFFUSE\n"
3065 "       half3 lightnormal = half3(normalize(LightVector));\n"
3066 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3067 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3068 "#ifdef USESPECULAR\n"
3069 "#ifdef USEEXACTSPECULARMATH\n"
3070 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3071 "#else\n"
3072 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3073 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3074 "#endif\n"
3075 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3076 "#endif\n"
3077 "#else\n"
3078 "       color.rgb = diffusetex * Color_Ambient;\n"
3079 "#endif\n"
3080 "       color.rgb *= LightColor;\n"
3081 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3082 "#if defined(USESHADOWMAP2D)\n"
3083 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3084 "#ifdef USESHADOWMAPVSDCT\n"
3085 ", Texture_CubeProjection\n"
3086 "#endif\n"
3087 "       ));\n"
3088 "\n"
3089 "#endif\n"
3090 "# ifdef USECUBEFILTER\n"
3091 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3092 "# endif\n"
3093 "\n"
3094 "#ifdef USESHADOWMAP2D\n"
3095 "#ifdef USESHADOWMAPVSDCT\n"
3096 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3097 "#else\n"
3098 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3099 "#endif\n"
3100 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3101 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3102 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3103 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3104 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3105 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3106 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3107 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3108 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3109 "//     color.r = half(shadowmaptc.z);\n"
3110 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3111 "//     color.r = half(shadowmaptc.z);\n"
3112 "//     color.r = 1;\n"
3113 "//     color.rgb = abs(CubeVector);\n"
3114 "#endif\n"
3115 "//     color.rgb = half3(1,1,1);\n"
3116 "#endif // MODE_LIGHTSOURCE\n"
3117 "\n"
3118 "\n"
3119 "\n"
3120 "\n"
3121 "#ifdef MODE_LIGHTDIRECTION\n"
3122 "#define SHADING\n"
3123 "#ifdef USEDIFFUSE\n"
3124 "       half3 lightnormal = half3(normalize(LightVector));\n"
3125 "#endif\n"
3126 "#define lightcolor LightColor\n"
3127 "#endif // MODE_LIGHTDIRECTION\n"
3128 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3129 "#define SHADING\n"
3130 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3131 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3132 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3133 "       // convert modelspace light vector to tangentspace\n"
3134 "       half3 lightnormal;\n"
3135 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3136 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3137 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3138 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3139 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3140 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3141 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3142 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3143 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3144 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3145 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3146 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3147 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3148 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3149 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3150 "#define SHADING\n"
3151 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3152 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3153 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3154 "#endif\n"
3155 "\n"
3156 "\n"
3157 "\n"
3158 "\n"
3159 "#ifdef MODE_LIGHTMAP\n"
3160 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3161 "#endif // MODE_LIGHTMAP\n"
3162 "#ifdef MODE_VERTEXCOLOR\n"
3163 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3164 "#endif // MODE_VERTEXCOLOR\n"
3165 "#ifdef MODE_FLATCOLOR\n"
3166 "       color.rgb = diffusetex * Color_Ambient;\n"
3167 "#endif // MODE_FLATCOLOR\n"
3168 "\n"
3169 "\n"
3170 "\n"
3171 "\n"
3172 "#ifdef SHADING\n"
3173 "# ifdef USEDIFFUSE\n"
3174 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3175 "#  ifdef USESPECULAR\n"
3176 "#   ifdef USEEXACTSPECULARMATH\n"
3177 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3178 "#   else\n"
3179 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3180 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3181 "#   endif\n"
3182 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3183 "#  else\n"
3184 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3185 "#  endif\n"
3186 "# else\n"
3187 "       color.rgb = diffusetex * Color_Ambient;\n"
3188 "# endif\n"
3189 "#endif\n"
3190 "\n"
3191 "#ifdef USESHADOWMAPORTHO\n"
3192 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3193 "#endif\n"
3194 "\n"
3195 "#ifdef USEDEFERREDLIGHTMAP\n"
3196 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3197 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3198 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3199 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3200 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3201 "#endif\n"
3202 "\n"
3203 "#ifdef USEGLOW\n"
3204 "#ifdef USEVERTEXTEXTUREBLEND\n"
3205 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3206 "#else\n"
3207 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3208 "#endif\n"
3209 "#endif\n"
3210 "\n"
3211 "#ifdef USEFOG\n"
3212 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3213 "#endif\n"
3214 "\n"
3215 "       // 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"
3216 "#ifdef USEREFLECTION\n"
3217 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3218 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3219 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3220 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3221 "       // FIXME temporary hack to detect the case that the reflection\n"
3222 "       // gets blackened at edges due to leaving the area that contains actual\n"
3223 "       // content.\n"
3224 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3225 "       // 'appening.\n"
3226 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3227 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3228 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3229 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3230 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3231 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3232 "#endif\n"
3233 "\n"
3234 "       gl_FragColor = float4(color);\n"
3235 "}\n"
3236 "#endif // FRAGMENT_SHADER\n"
3237 "\n"
3238 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3239 "#endif // !MODE_DEFERREDGEOMETRY\n"
3240 "#endif // !MODE_WATER\n"
3241 "#endif // !MODE_REFRACTION\n"
3242 "#endif // !MODE_BLOOMBLUR\n"
3243 "#endif // !MODE_GENERIC\n"
3244 "#endif // !MODE_POSTPROCESS\n"
3245 "#endif // !MODE_SHOWDEPTH\n"
3246 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3247 ;
3248
3249 char *glslshaderstring = NULL;
3250 char *cgshaderstring = NULL;
3251 char *hlslshaderstring = NULL;
3252
3253 //=======================================================================================================================================================
3254
3255 typedef struct shaderpermutationinfo_s
3256 {
3257         const char *pretext;
3258         const char *name;
3259 }
3260 shaderpermutationinfo_t;
3261
3262 typedef struct shadermodeinfo_s
3263 {
3264         const char *vertexfilename;
3265         const char *geometryfilename;
3266         const char *fragmentfilename;
3267         const char *pretext;
3268         const char *name;
3269 }
3270 shadermodeinfo_t;
3271
3272 typedef enum shaderpermutation_e
3273 {
3274         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3275         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3276         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3277         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3278         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3279         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3280         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3281         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3282         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3283         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3284         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3285         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3286         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3287         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3288         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3289         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3290         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3291         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3292         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3293         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3294         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3295         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3296         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3297         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3298         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3299         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3300         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3301         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3302         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3303 }
3304 shaderpermutation_t;
3305
3306 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3307 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3308 {
3309         {"#define USEDIFFUSE\n", " diffuse"},
3310         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3311         {"#define USEVIEWTINT\n", " viewtint"},
3312         {"#define USECOLORMAPPING\n", " colormapping"},
3313         {"#define USESATURATION\n", " saturation"},
3314         {"#define USEFOGINSIDE\n", " foginside"},
3315         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3316         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3317         {"#define USEGAMMARAMPS\n", " gammaramps"},
3318         {"#define USECUBEFILTER\n", " cubefilter"},
3319         {"#define USEGLOW\n", " glow"},
3320         {"#define USEBLOOM\n", " bloom"},
3321         {"#define USESPECULAR\n", " specular"},
3322         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3323         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3324         {"#define USEREFLECTION\n", " reflection"},
3325         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3326         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3327         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3328         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3329         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3330         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3331         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3332         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3333         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3334         {"#define USEALPHAKILL\n", " alphakill"},
3335         {"#define USEREFLECTCUBE\n", " reflectcube"},
3336 };
3337
3338 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3339 typedef enum shadermode_e
3340 {
3341         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3342         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3343         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3344         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3345         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3346         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3347         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3348         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3349         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3350         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3351         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3352         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3353         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3354         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3355         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3356         SHADERMODE_COUNT
3357 }
3358 shadermode_t;
3359
3360 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3361 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3362 {
3363         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3364         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3365         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3366         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3367         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3368         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3369         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3370         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3371         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3372         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3373         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3374         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3375         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3376         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3377         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3378 };
3379
3380 #ifdef SUPPORTCG
3381 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3382 {
3383         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3384         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3385         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3386         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3387         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3388         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3389         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3390         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3391         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3392         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3393         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3394         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3395         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3396         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3397         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3398 };
3399 #endif
3400
3401 #ifdef SUPPORTD3D
3402 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3403 {
3404         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3405         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3406         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3407         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3408         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3409         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3410         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3411         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3412         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3413         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3414         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3415         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3416         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3417         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3419 };
3420 #endif
3421
3422 struct r_glsl_permutation_s;
3423 typedef struct r_glsl_permutation_s
3424 {
3425         /// hash lookup data
3426         struct r_glsl_permutation_s *hashnext;
3427         unsigned int mode;
3428         unsigned int permutation;
3429
3430         /// indicates if we have tried compiling this permutation already
3431         qboolean compiled;
3432         /// 0 if compilation failed
3433         int program;
3434         /// locations of detected uniforms in program object, or -1 if not found
3435         int loc_Texture_First;
3436         int loc_Texture_Second;
3437         int loc_Texture_GammaRamps;
3438         int loc_Texture_Normal;
3439         int loc_Texture_Color;
3440         int loc_Texture_Gloss;
3441         int loc_Texture_Glow;
3442         int loc_Texture_SecondaryNormal;
3443         int loc_Texture_SecondaryColor;
3444         int loc_Texture_SecondaryGloss;
3445         int loc_Texture_SecondaryGlow;
3446         int loc_Texture_Pants;
3447         int loc_Texture_Shirt;
3448         int loc_Texture_FogHeightTexture;
3449         int loc_Texture_FogMask;
3450         int loc_Texture_Lightmap;
3451         int loc_Texture_Deluxemap;
3452         int loc_Texture_Attenuation;
3453         int loc_Texture_Cube;
3454         int loc_Texture_Refraction;
3455         int loc_Texture_Reflection;
3456         int loc_Texture_ShadowMap2D;
3457         int loc_Texture_CubeProjection;
3458         int loc_Texture_ScreenDepth;
3459         int loc_Texture_ScreenNormalMap;
3460         int loc_Texture_ScreenDiffuse;
3461         int loc_Texture_ScreenSpecular;
3462         int loc_Texture_ReflectMask;
3463         int loc_Texture_ReflectCube;
3464         int loc_Alpha;
3465         int loc_BloomBlur_Parameters;
3466         int loc_ClientTime;
3467         int loc_Color_Ambient;
3468         int loc_Color_Diffuse;
3469         int loc_Color_Specular;
3470         int loc_Color_Glow;
3471         int loc_Color_Pants;
3472         int loc_Color_Shirt;
3473         int loc_DeferredColor_Ambient;
3474         int loc_DeferredColor_Diffuse;
3475         int loc_DeferredColor_Specular;
3476         int loc_DeferredMod_Diffuse;
3477         int loc_DeferredMod_Specular;
3478         int loc_DistortScaleRefractReflect;
3479         int loc_EyePosition;
3480         int loc_FogColor;
3481         int loc_FogHeightFade;
3482         int loc_FogPlane;
3483         int loc_FogPlaneViewDist;
3484         int loc_FogRangeRecip;
3485         int loc_LightColor;
3486         int loc_LightDir;
3487         int loc_LightPosition;
3488         int loc_OffsetMapping_Scale;
3489         int loc_PixelSize;
3490         int loc_ReflectColor;
3491         int loc_ReflectFactor;
3492         int loc_ReflectOffset;
3493         int loc_RefractColor;
3494         int loc_Saturation;
3495         int loc_ScreenCenterRefractReflect;
3496         int loc_ScreenScaleRefractReflect;
3497         int loc_ScreenToDepth;
3498         int loc_ShadowMap_Parameters;
3499         int loc_ShadowMap_TextureScale;
3500         int loc_SpecularPower;
3501         int loc_UserVec1;
3502         int loc_UserVec2;
3503         int loc_UserVec3;
3504         int loc_UserVec4;
3505         int loc_ViewTintColor;
3506         int loc_ViewToLight;
3507         int loc_ModelToLight;
3508         int loc_TexMatrix;
3509         int loc_BackgroundTexMatrix;
3510         int loc_ModelViewProjectionMatrix;
3511         int loc_ModelViewMatrix;
3512         int loc_PixelToScreenTexCoord;
3513         int loc_ModelToReflectCube;
3514         int loc_ShadowMapMatrix;
3515         int loc_BloomColorSubtract;
3516 }
3517 r_glsl_permutation_t;
3518
3519 #define SHADERPERMUTATION_HASHSIZE 256
3520
3521 /// information about each possible shader permutation
3522 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3523 /// currently selected permutation
3524 r_glsl_permutation_t *r_glsl_permutation;
3525 /// storage for permutations linked in the hash table
3526 memexpandablearray_t r_glsl_permutationarray;
3527
3528 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3529 {
3530         //unsigned int hashdepth = 0;
3531         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3532         r_glsl_permutation_t *p;
3533         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3534         {
3535                 if (p->mode == mode && p->permutation == permutation)
3536                 {
3537                         //if (hashdepth > 10)
3538                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3539                         return p;
3540                 }
3541                 //hashdepth++;
3542         }
3543         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3544         p->mode = mode;
3545         p->permutation = permutation;
3546         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3547         r_glsl_permutationhash[mode][hashindex] = p;
3548         //if (hashdepth > 10)
3549         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3550         return p;
3551 }
3552
3553 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3554 {
3555         char *shaderstring;
3556         if (!filename || !filename[0])
3557                 return NULL;
3558         if (!strcmp(filename, "glsl/default.glsl"))
3559         {
3560                 if (!glslshaderstring)
3561                 {
3562                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3563                         if (glslshaderstring)
3564                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3565                         else
3566                                 glslshaderstring = (char *)builtinshaderstring;
3567                 }
3568                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3569                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3570                 return shaderstring;
3571         }
3572         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3573         if (shaderstring)
3574         {
3575                 if (printfromdisknotice)
3576                         Con_DPrintf("from disk %s... ", filename);
3577                 return shaderstring;
3578         }
3579         return shaderstring;
3580 }
3581
3582 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3583 {
3584         int i;
3585         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3586         int vertstrings_count = 0;
3587         int geomstrings_count = 0;
3588         int fragstrings_count = 0;
3589         char *vertexstring, *geometrystring, *fragmentstring;
3590         const char *vertstrings_list[32+3];
3591         const char *geomstrings_list[32+3];
3592         const char *fragstrings_list[32+3];
3593         char permutationname[256];
3594
3595         if (p->compiled)
3596                 return;
3597         p->compiled = true;
3598         p->program = 0;
3599
3600         permutationname[0] = 0;
3601         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3602         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3603         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3604
3605         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3606
3607         // the first pretext is which type of shader to compile as
3608         // (later these will all be bound together as a program object)
3609         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3610         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3611         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3612
3613         // the second pretext is the mode (for example a light source)
3614         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3615         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3616         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3617         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3618
3619         // now add all the permutation pretexts
3620         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3621         {
3622                 if (permutation & (1<<i))
3623                 {
3624                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3625                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3626                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3627                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3628                 }
3629                 else
3630                 {
3631                         // keep line numbers correct
3632                         vertstrings_list[vertstrings_count++] = "\n";
3633                         geomstrings_list[geomstrings_count++] = "\n";
3634                         fragstrings_list[fragstrings_count++] = "\n";
3635                 }
3636         }
3637
3638         // now append the shader text itself
3639         vertstrings_list[vertstrings_count++] = vertexstring;
3640         geomstrings_list[geomstrings_count++] = geometrystring;
3641         fragstrings_list[fragstrings_count++] = fragmentstring;
3642
3643         // if any sources were NULL, clear the respective list
3644         if (!vertexstring)
3645                 vertstrings_count = 0;
3646         if (!geometrystring)
3647                 geomstrings_count = 0;
3648         if (!fragmentstring)
3649                 fragstrings_count = 0;
3650
3651         // compile the shader program
3652         if (vertstrings_count + geomstrings_count + fragstrings_count)
3653                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3654         if (p->program)
3655         {
3656                 CHECKGLERROR
3657                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3658                 // look up all the uniform variable names we care about, so we don't
3659                 // have to look them up every time we set them
3660
3661                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3662                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3663                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3664                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3665                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3666                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3667                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3668                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3669                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3670                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3671                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3672                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3673                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3674                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3675                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3676                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3677                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3678                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3679                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3680                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3681                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3682                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3683                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3684                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3685                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3686                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3687                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3688                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3689                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3690                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3691                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3692                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3693                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3694                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3695                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3696                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3697                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3698                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3699                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3700                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3701                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3702                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3703                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3704                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3705                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3706                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3707                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3708                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3709                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3710                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3711                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3712                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3713                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3714                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3715                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3716                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3717                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3718                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3719                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3720                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3721                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3722                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3723                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3724                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3725                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3726                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3727                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3728                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3729                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3730                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3731                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3732                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3733                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3734                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3735                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3736                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3737                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3738                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3739                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3740                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3741                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3742                 // initialize the samplers to refer to the texture units we use
3743                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3744                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3745                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3746                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3747                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3748                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3749                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3750                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3751                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3752                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3753                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3754                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3755                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3756                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3757                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3758                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3759                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3760                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3761                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3762                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3763                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3764                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3765                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3766                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3767                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3768                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3769                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3770                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3771                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3772                 CHECKGLERROR
3773                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3774         }
3775         else
3776                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3777
3778         // free the strings
3779         if (vertexstring)
3780                 Mem_Free(vertexstring);
3781         if (geometrystring)
3782                 Mem_Free(geometrystring);
3783         if (fragmentstring)
3784                 Mem_Free(fragmentstring);
3785 }
3786
3787 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3788 {
3789         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3790         if (r_glsl_permutation != perm)
3791         {
3792                 r_glsl_permutation = perm;
3793                 if (!r_glsl_permutation->program)
3794                 {
3795                         if (!r_glsl_permutation->compiled)
3796                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3797                         if (!r_glsl_permutation->program)
3798                         {
3799                                 // remove features until we find a valid permutation
3800                                 int i;
3801                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3802                                 {
3803                                         // reduce i more quickly whenever it would not remove any bits
3804                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3805                                         if (!(permutation & j))
3806                                                 continue;
3807                                         permutation -= j;
3808                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3809                                         if (!r_glsl_permutation->compiled)
3810                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3811                                         if (r_glsl_permutation->program)
3812                                                 break;
3813                                 }
3814                                 if (i >= SHADERPERMUTATION_COUNT)
3815                                 {
3816                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3817                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3818                                         qglUseProgramObjectARB(0);CHECKGLERROR
3819                                         return; // no bit left to clear, entire mode is broken
3820                                 }
3821                         }
3822                 }
3823                 CHECKGLERROR
3824                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3825         }
3826         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3827         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3828         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3829 }
3830
3831 #ifdef SUPPORTCG
3832 #include <Cg/cgGL.h>
3833 struct r_cg_permutation_s;
3834 typedef struct r_cg_permutation_s
3835 {
3836         /// hash lookup data
3837         struct r_cg_permutation_s *hashnext;
3838         unsigned int mode;
3839         unsigned int permutation;
3840
3841         /// indicates if we have tried compiling this permutation already
3842         qboolean compiled;
3843         /// 0 if compilation failed
3844         CGprogram vprogram;
3845         CGprogram fprogram;
3846         /// locations of detected parameters in programs, or NULL if not found
3847         CGparameter vp_EyePosition;
3848         CGparameter vp_FogPlane;
3849         CGparameter vp_LightDir;
3850         CGparameter vp_LightPosition;
3851         CGparameter vp_ModelToLight;
3852         CGparameter vp_TexMatrix;
3853         CGparameter vp_BackgroundTexMatrix;
3854         CGparameter vp_ModelViewProjectionMatrix;
3855         CGparameter vp_ModelViewMatrix;
3856         CGparameter vp_ShadowMapMatrix;
3857
3858         CGparameter fp_Texture_First;
3859         CGparameter fp_Texture_Second;
3860         CGparameter fp_Texture_GammaRamps;
3861         CGparameter fp_Texture_Normal;
3862         CGparameter fp_Texture_Color;
3863         CGparameter fp_Texture_Gloss;
3864         CGparameter fp_Texture_Glow;
3865         CGparameter fp_Texture_SecondaryNormal;
3866         CGparameter fp_Texture_SecondaryColor;
3867         CGparameter fp_Texture_SecondaryGloss;
3868         CGparameter fp_Texture_SecondaryGlow;
3869         CGparameter fp_Texture_Pants;
3870         CGparameter fp_Texture_Shirt;
3871         CGparameter fp_Texture_FogHeightTexture;
3872         CGparameter fp_Texture_FogMask;
3873         CGparameter fp_Texture_Lightmap;
3874         CGparameter fp_Texture_Deluxemap;
3875         CGparameter fp_Texture_Attenuation;
3876         CGparameter fp_Texture_Cube;
3877         CGparameter fp_Texture_Refraction;
3878         CGparameter fp_Texture_Reflection;
3879         CGparameter fp_Texture_ShadowMap2D;
3880         CGparameter fp_Texture_CubeProjection;
3881         CGparameter fp_Texture_ScreenDepth;
3882         CGparameter fp_Texture_ScreenNormalMap;
3883         CGparameter fp_Texture_ScreenDiffuse;
3884         CGparameter fp_Texture_ScreenSpecular;
3885         CGparameter fp_Texture_ReflectMask;
3886         CGparameter fp_Texture_ReflectCube;
3887         CGparameter fp_Alpha;
3888         CGparameter fp_BloomBlur_Parameters;
3889         CGparameter fp_ClientTime;
3890         CGparameter fp_Color_Ambient;
3891         CGparameter fp_Color_Diffuse;
3892         CGparameter fp_Color_Specular;
3893         CGparameter fp_Color_Glow;
3894         CGparameter fp_Color_Pants;
3895         CGparameter fp_Color_Shirt;
3896         CGparameter fp_DeferredColor_Ambient;
3897         CGparameter fp_DeferredColor_Diffuse;
3898         CGparameter fp_DeferredColor_Specular;
3899         CGparameter fp_DeferredMod_Diffuse;
3900         CGparameter fp_DeferredMod_Specular;
3901         CGparameter fp_DistortScaleRefractReflect;
3902         CGparameter fp_EyePosition;
3903         CGparameter fp_FogColor;
3904         CGparameter fp_FogHeightFade;
3905         CGparameter fp_FogPlane;
3906         CGparameter fp_FogPlaneViewDist;
3907         CGparameter fp_FogRangeRecip;
3908         CGparameter fp_LightColor;
3909         CGparameter fp_LightDir;
3910         CGparameter fp_LightPosition;
3911         CGparameter fp_OffsetMapping_Scale;
3912         CGparameter fp_PixelSize;
3913         CGparameter fp_ReflectColor;
3914         CGparameter fp_ReflectFactor;
3915         CGparameter fp_ReflectOffset;
3916         CGparameter fp_RefractColor;
3917         CGparameter fp_Saturation;
3918         CGparameter fp_ScreenCenterRefractReflect;
3919         CGparameter fp_ScreenScaleRefractReflect;
3920         CGparameter fp_ScreenToDepth;
3921         CGparameter fp_ShadowMap_Parameters;
3922         CGparameter fp_ShadowMap_TextureScale;
3923         CGparameter fp_SpecularPower;
3924         CGparameter fp_UserVec1;
3925         CGparameter fp_UserVec2;
3926         CGparameter fp_UserVec3;
3927         CGparameter fp_UserVec4;
3928         CGparameter fp_ViewTintColor;
3929         CGparameter fp_ViewToLight;
3930         CGparameter fp_PixelToScreenTexCoord;
3931         CGparameter fp_ModelToReflectCube;
3932         CGparameter fp_BloomColorSubtract;
3933 }
3934 r_cg_permutation_t;
3935
3936 /// information about each possible shader permutation
3937 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3938 /// currently selected permutation
3939 r_cg_permutation_t *r_cg_permutation;
3940 /// storage for permutations linked in the hash table
3941 memexpandablearray_t r_cg_permutationarray;
3942
3943 #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));}}
3944
3945 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3946 {
3947         //unsigned int hashdepth = 0;
3948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3949         r_cg_permutation_t *p;
3950         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3951         {
3952                 if (p->mode == mode && p->permutation == permutation)
3953                 {
3954                         //if (hashdepth > 10)
3955                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3956                         return p;
3957                 }
3958                 //hashdepth++;
3959         }
3960         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3961         p->mode = mode;
3962         p->permutation = permutation;
3963         p->hashnext = r_cg_permutationhash[mode][hashindex];
3964         r_cg_permutationhash[mode][hashindex] = p;
3965         //if (hashdepth > 10)
3966         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3967         return p;
3968 }
3969
3970 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3971 {
3972         char *shaderstring;
3973         if (!filename || !filename[0])
3974                 return NULL;
3975         if (!strcmp(filename, "cg/default.cg"))
3976         {
3977                 if (!cgshaderstring)
3978                 {
3979                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3980                         if (cgshaderstring)
3981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3982                         else
3983                                 cgshaderstring = (char *)builtincgshaderstring;
3984                 }
3985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3986                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3987                 return shaderstring;
3988         }
3989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3990         if (shaderstring)
3991         {
3992                 if (printfromdisknotice)
3993                         Con_DPrintf("from disk %s... ", filename);
3994                 return shaderstring;
3995         }
3996         return shaderstring;
3997 }
3998
3999 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4000 {
4001         // TODO: load or create .fp and .vp shader files
4002 }
4003
4004 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4005 {
4006         int i;
4007         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4008         int vertstrings_count = 0, vertstring_length = 0;
4009         int geomstrings_count = 0, geomstring_length = 0;
4010         int fragstrings_count = 0, fragstring_length = 0;
4011         char *t;
4012         char *vertexstring, *geometrystring, *fragmentstring;
4013         char *vertstring, *geomstring, *fragstring;
4014         const char *vertstrings_list[32+3];
4015         const char *geomstrings_list[32+3];
4016         const char *fragstrings_list[32+3];
4017         char permutationname[256];
4018         char cachename[256];
4019         CGprofile vertexProfile;
4020         CGprofile fragmentProfile;
4021
4022         if (p->compiled)
4023                 return;
4024         p->compiled = true;
4025         p->vprogram = NULL;
4026         p->fprogram = NULL;
4027
4028         permutationname[0] = 0;
4029         cachename[0] = 0;
4030         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4031         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4032         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4033
4034         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4035         strlcat(cachename, "cg/", sizeof(cachename));
4036
4037         // the first pretext is which type of shader to compile as
4038         // (later these will all be bound together as a program object)
4039         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4040         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4041         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4042
4043         // the second pretext is the mode (for example a light source)
4044         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4045         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4046         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4047         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4048         strlcat(cachename, modeinfo->name, sizeof(cachename));
4049
4050         // now add all the permutation pretexts
4051         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4052         {
4053                 if (permutation & (1<<i))
4054                 {
4055                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4056                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4057                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4058                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4059                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4060                 }
4061                 else
4062                 {
4063                         // keep line numbers correct
4064                         vertstrings_list[vertstrings_count++] = "\n";
4065                         geomstrings_list[geomstrings_count++] = "\n";
4066                         fragstrings_list[fragstrings_count++] = "\n";
4067                 }
4068         }
4069
4070         // replace spaces in the cachename with _ characters
4071         for (i = 0;cachename[i];i++)
4072                 if (cachename[i] == ' ')
4073                         cachename[i] = '_';
4074
4075         // now append the shader text itself
4076         vertstrings_list[vertstrings_count++] = vertexstring;
4077         geomstrings_list[geomstrings_count++] = geometrystring;
4078         fragstrings_list[fragstrings_count++] = fragmentstring;
4079
4080         // if any sources were NULL, clear the respective list
4081         if (!vertexstring)
4082                 vertstrings_count = 0;
4083         if (!geometrystring)
4084                 geomstrings_count = 0;
4085         if (!fragmentstring)
4086                 fragstrings_count = 0;
4087
4088         vertstring_length = 0;
4089         for (i = 0;i < vertstrings_count;i++)
4090                 vertstring_length += strlen(vertstrings_list[i]);
4091         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4092         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4093                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4094
4095         geomstring_length = 0;
4096         for (i = 0;i < geomstrings_count;i++)
4097                 geomstring_length += strlen(geomstrings_list[i]);
4098         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4099         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4100                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4101
4102         fragstring_length = 0;
4103         for (i = 0;i < fragstrings_count;i++)
4104                 fragstring_length += strlen(fragstrings_list[i]);
4105         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4106         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4107                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4108
4109         CHECKGLERROR
4110         CHECKCGERROR
4111         //vertexProfile = CG_PROFILE_ARBVP1;
4112         //fragmentProfile = CG_PROFILE_ARBFP1;
4113         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4114         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4115         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4116         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4117         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4118         CHECKGLERROR
4119
4120         // try to load the cached shader, or generate one
4121         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4122
4123         // if caching failed, do a dynamic compile for now
4124         CHECKCGERROR
4125         if (vertstring[0] && !p->vprogram)
4126                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4127         CHECKCGERROR
4128         if (fragstring[0] && !p->fprogram)
4129                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4130         CHECKCGERROR
4131
4132         // look up all the uniform variable names we care about, so we don't
4133         // have to look them up every time we set them
4134         if (p->vprogram)
4135         {
4136                 CHECKCGERROR
4137                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4138                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4139                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4140                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4141                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4142                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4143                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4144                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4145                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4146                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4147                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4148                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4149                 CHECKCGERROR
4150         }
4151         if (p->fprogram)
4152         {
4153                 CHECKCGERROR
4154                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4155                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4156                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4157                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4158                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4159                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4160                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4161                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4162                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4163                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4164                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4165                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4166                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4167                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4168                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4169                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4170                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4171                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4172                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4173                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4174                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4175                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4176                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4177                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4178                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4179                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4180                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4181                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4182                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4183                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4184                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4185                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4186                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4187                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4188                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4189                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4190                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4191                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4192                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4193                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4194                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4195                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4196                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4197                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4198                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4199                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4200                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4201                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4202                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4203                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4204                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4205                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4206                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4207                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4208                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4209                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4210                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4211                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4212                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4213                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4214                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4215                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4216                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4217                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4218                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4219                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4220                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4221                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4222                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4223                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4224                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4225                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4226                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4227                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4228                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4229                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4230                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4231                 CHECKCGERROR
4232         }
4233
4234         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4235                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4236         else
4237                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4238
4239         // free the strings
4240         if (vertstring)
4241                 Mem_Free(vertstring);
4242         if (geomstring)
4243                 Mem_Free(geomstring);
4244         if (fragstring)
4245                 Mem_Free(fragstring);
4246         if (vertexstring)
4247                 Mem_Free(vertexstring);
4248         if (geometrystring)
4249                 Mem_Free(geometrystring);
4250         if (fragmentstring)
4251                 Mem_Free(fragmentstring);
4252 }
4253
4254 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4255 {
4256         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4257         CHECKGLERROR
4258         CHECKCGERROR
4259         if (r_cg_permutation != perm)
4260         {
4261                 r_cg_permutation = perm;
4262                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4263                 {
4264                         if (!r_cg_permutation->compiled)
4265                                 R_CG_CompilePermutation(perm, mode, permutation);
4266                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4267                         {
4268                                 // remove features until we find a valid permutation
4269                                 int i;
4270                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271                                 {
4272                                         // reduce i more quickly whenever it would not remove any bits
4273                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4274                                         if (!(permutation & j))
4275                                                 continue;
4276                                         permutation -= j;
4277                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4278                                         if (!r_cg_permutation->compiled)
4279                                                 R_CG_CompilePermutation(perm, mode, permutation);
4280                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4281                                                 break;
4282                                 }
4283                                 if (i >= SHADERPERMUTATION_COUNT)
4284                                 {
4285                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4286                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4287                                         return; // no bit left to clear, entire mode is broken
4288                                 }
4289                         }
4290                 }
4291                 CHECKGLERROR
4292                 CHECKCGERROR
4293                 if (r_cg_permutation->vprogram)
4294                 {
4295                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4296                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4297                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4298                 }
4299                 else
4300                 {
4301                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4302                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4303                 }
4304                 if (r_cg_permutation->fprogram)
4305                 {
4306                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4307                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4308                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4309                 }
4310                 else
4311                 {
4312                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4313                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4314                 }
4315         }
4316         CHECKCGERROR
4317         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4318         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4319         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4320 }
4321
4322 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4323 {
4324         cgGLSetTextureParameter(param, R_GetTexture(tex));
4325         cgGLEnableTextureParameter(param);
4326 }
4327 #endif
4328
4329 #ifdef SUPPORTD3D
4330
4331 #ifdef SUPPORTD3D
4332 #include <d3d9.h>
4333 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4334 extern D3DCAPS9 vid_d3d9caps;
4335 #endif
4336
4337 struct r_hlsl_permutation_s;
4338 typedef struct r_hlsl_permutation_s
4339 {
4340         /// hash lookup data
4341         struct r_hlsl_permutation_s *hashnext;
4342         unsigned int mode;
4343         unsigned int permutation;
4344
4345         /// indicates if we have tried compiling this permutation already
4346         qboolean compiled;
4347         /// NULL if compilation failed
4348         IDirect3DVertexShader9 *vertexshader;
4349         IDirect3DPixelShader9 *pixelshader;
4350 }
4351 r_hlsl_permutation_t;
4352
4353 typedef enum D3DVSREGISTER_e
4354 {
4355         D3DVSREGISTER_TexMatrix = 0, // float4x4
4356         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4357         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4358         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4359         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4360         D3DVSREGISTER_ModelToLight = 20, // float4x4
4361         D3DVSREGISTER_EyePosition = 24,
4362         D3DVSREGISTER_FogPlane = 25,
4363         D3DVSREGISTER_LightDir = 26,
4364         D3DVSREGISTER_LightPosition = 27,
4365 }
4366 D3DVSREGISTER_t;
4367
4368 typedef enum D3DPSREGISTER_e
4369 {
4370         D3DPSREGISTER_Alpha = 0,
4371         D3DPSREGISTER_BloomBlur_Parameters = 1,
4372         D3DPSREGISTER_ClientTime = 2,
4373         D3DPSREGISTER_Color_Ambient = 3,
4374         D3DPSREGISTER_Color_Diffuse = 4,
4375         D3DPSREGISTER_Color_Specular = 5,
4376         D3DPSREGISTER_Color_Glow = 6,
4377         D3DPSREGISTER_Color_Pants = 7,
4378         D3DPSREGISTER_Color_Shirt = 8,
4379         D3DPSREGISTER_DeferredColor_Ambient = 9,
4380         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4381         D3DPSREGISTER_DeferredColor_Specular = 11,
4382         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4383         D3DPSREGISTER_DeferredMod_Specular = 13,
4384         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4385         D3DPSREGISTER_EyePosition = 15, // unused
4386         D3DPSREGISTER_FogColor = 16,
4387         D3DPSREGISTER_FogHeightFade = 17,
4388         D3DPSREGISTER_FogPlane = 18,
4389         D3DPSREGISTER_FogPlaneViewDist = 19,
4390         D3DPSREGISTER_FogRangeRecip = 20,
4391         D3DPSREGISTER_LightColor = 21,
4392         D3DPSREGISTER_LightDir = 22, // unused
4393         D3DPSREGISTER_LightPosition = 23,
4394         D3DPSREGISTER_OffsetMapping_Scale = 24,
4395         D3DPSREGISTER_PixelSize = 25,
4396         D3DPSREGISTER_ReflectColor = 26,
4397         D3DPSREGISTER_ReflectFactor = 27,
4398         D3DPSREGISTER_ReflectOffset = 28,
4399         D3DPSREGISTER_RefractColor = 29,
4400         D3DPSREGISTER_Saturation = 30,
4401         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4402         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4403         D3DPSREGISTER_ScreenToDepth = 33,
4404         D3DPSREGISTER_ShadowMap_Parameters = 34,
4405         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4406         D3DPSREGISTER_SpecularPower = 36,
4407         D3DPSREGISTER_UserVec1 = 37,
4408         D3DPSREGISTER_UserVec2 = 38,
4409         D3DPSREGISTER_UserVec3 = 39,
4410         D3DPSREGISTER_UserVec4 = 40,
4411         D3DPSREGISTER_ViewTintColor = 41,
4412         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4413         D3DPSREGISTER_BloomColorSubtract = 43,
4414         D3DPSREGISTER_ViewToLight = 44, // float4x4
4415         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4416         // next at 52
4417 }
4418 D3DPSREGISTER_t;
4419
4420 /// information about each possible shader permutation
4421 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4422 /// currently selected permutation
4423 r_hlsl_permutation_t *r_hlsl_permutation;
4424 /// storage for permutations linked in the hash table
4425 memexpandablearray_t r_hlsl_permutationarray;
4426
4427 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4428 {
4429         //unsigned int hashdepth = 0;
4430         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4431         r_hlsl_permutation_t *p;
4432         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4433         {
4434                 if (p->mode == mode && p->permutation == permutation)
4435                 {
4436                         //if (hashdepth > 10)
4437                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4438                         return p;
4439                 }
4440                 //hashdepth++;
4441         }
4442         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4443         p->mode = mode;
4444         p->permutation = permutation;
4445         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4446         r_hlsl_permutationhash[mode][hashindex] = p;
4447         //if (hashdepth > 10)
4448         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4449         return p;
4450 }
4451
4452 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4453 {
4454         char *shaderstring;
4455         if (!filename || !filename[0])
4456                 return NULL;
4457         if (!strcmp(filename, "hlsl/default.hlsl"))
4458         {
4459                 if (!hlslshaderstring)
4460                 {
4461                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4462                         if (hlslshaderstring)
4463                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4464                         else
4465                                 hlslshaderstring = (char *)builtincgshaderstring;
4466                 }
4467                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4468                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4469                 return shaderstring;
4470         }
4471         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4472         if (shaderstring)
4473         {
4474                 if (printfromdisknotice)
4475                         Con_DPrintf("from disk %s... ", filename);
4476                 return shaderstring;
4477         }
4478         return shaderstring;
4479 }
4480
4481 #include <d3dx9.h>
4482 //#include <d3dx9shader.h>
4483 //#include <d3dx9mesh.h>
4484
4485 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4486 {
4487         DWORD *vsbin = NULL;
4488         DWORD *psbin = NULL;
4489         fs_offset_t vsbinsize;
4490         fs_offset_t psbinsize;
4491 //      IDirect3DVertexShader9 *vs = NULL;
4492 //      IDirect3DPixelShader9 *ps = NULL;
4493         ID3DXBuffer *vslog = NULL;
4494         ID3DXBuffer *vsbuffer = NULL;
4495         ID3DXConstantTable *vsconstanttable = NULL;
4496         ID3DXBuffer *pslog = NULL;
4497         ID3DXBuffer *psbuffer = NULL;
4498         ID3DXConstantTable *psconstanttable = NULL;
4499         int vsresult = 0;
4500         int psresult = 0;
4501         char temp[MAX_INPUTLINE];
4502         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4503         qboolean debugshader = gl_paranoid.integer != 0;
4504         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4505         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4506         if (!debugshader)
4507         {
4508                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4509                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4510         }
4511         if ((!vsbin && vertstring) || (!psbin && fragstring))
4512         {
4513                 const char* dllnames_d3dx9 [] =
4514                 {
4515                         "d3dx9_43.dll",
4516                         "d3dx9_42.dll",
4517                         "d3dx9_41.dll",
4518                         "d3dx9_40.dll",
4519                         "d3dx9_39.dll",
4520                         "d3dx9_38.dll",
4521                         "d3dx9_37.dll",
4522                         "d3dx9_36.dll",
4523                         "d3dx9_35.dll",
4524                         "d3dx9_34.dll",
4525                         "d3dx9_33.dll",
4526                         "d3dx9_32.dll",
4527                         "d3dx9_31.dll",
4528                         "d3dx9_30.dll",
4529                         "d3dx9_29.dll",
4530                         "d3dx9_28.dll",
4531                         "d3dx9_27.dll",
4532                         "d3dx9_26.dll",
4533                         "d3dx9_25.dll",
4534                         "d3dx9_24.dll",
4535                         NULL
4536                 };
4537                 dllhandle_t d3dx9_dll = NULL;
4538                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4539                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4540                 dllfunction_t d3dx9_dllfuncs[] =
4541                 {
4542                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4543                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4544                         {NULL, NULL}
4545                 };
4546                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4547                 {
4548                         DWORD shaderflags = 0;
4549                         if (debugshader)
4550                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4551                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4552                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4553                         if (vertstring && vertstring[0])
4554                         {
4555                                 if (debugshader)
4556                                 {
4557                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4558                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4559                                 }
4560                                 else
4561                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4562                                 if (vsbuffer)
4563                                 {
4564                                         vsbinsize = vsbuffer->GetBufferSize();
4565                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4566                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4567                                         vsbuffer->Release();
4568                                 }
4569                                 if (vslog)
4570                                 {
4571                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4572                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4573                                         vslog->Release();
4574                                 }
4575                         }
4576                         if (fragstring && fragstring[0])
4577                         {
4578                                 if (debugshader)
4579                                 {
4580                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4581                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4582                                 }
4583                                 else
4584                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4585                                 if (psbuffer)
4586                                 {
4587                                         psbinsize = psbuffer->GetBufferSize();
4588                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4589                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4590                                         psbuffer->Release();
4591                                 }
4592                                 if (pslog)
4593                                 {
4594                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4595                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4596                                         pslog->Release();
4597                                 }
4598                         }
4599                         Sys_UnloadLibrary(&d3dx9_dll);
4600                 }
4601                 else
4602                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4603         }
4604         if (vsbin && psbin)
4605         {
4606                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4607                 if (FAILED(vsresult))
4608                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4609                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4610                 if (FAILED(psresult))
4611                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4612         }
4613         // free the shader data
4614         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4615         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4616 }
4617
4618 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4619 {
4620         int i;
4621         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4622         int vertstrings_count = 0, vertstring_length = 0;
4623         int geomstrings_count = 0, geomstring_length = 0;
4624         int fragstrings_count = 0, fragstring_length = 0;
4625         char *t;
4626         char *vertexstring, *geometrystring, *fragmentstring;
4627         char *vertstring, *geomstring, *fragstring;
4628         const char *vertstrings_list[32+3];
4629         const char *geomstrings_list[32+3];
4630         const char *fragstrings_list[32+3];
4631         char permutationname[256];
4632         char cachename[256];
4633
4634         if (p->compiled)
4635                 return;
4636         p->compiled = true;
4637         p->vertexshader = NULL;
4638         p->pixelshader = NULL;
4639
4640         permutationname[0] = 0;
4641         cachename[0] = 0;
4642         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4643         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4644         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4645
4646         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4647         strlcat(cachename, "hlsl/", sizeof(cachename));
4648
4649         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4650         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4651         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4652         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4653
4654         // the first pretext is which type of shader to compile as
4655         // (later these will all be bound together as a program object)
4656         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4657         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4658         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4659
4660         // the second pretext is the mode (for example a light source)
4661         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4662         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4663         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4664         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4665         strlcat(cachename, modeinfo->name, sizeof(cachename));
4666
4667         // now add all the permutation pretexts
4668         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4669         {
4670                 if (permutation & (1<<i))
4671                 {
4672                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4673                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4674                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4675                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4676                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4677                 }
4678                 else
4679                 {
4680                         // keep line numbers correct
4681                         vertstrings_list[vertstrings_count++] = "\n";
4682                         geomstrings_list[geomstrings_count++] = "\n";
4683                         fragstrings_list[fragstrings_count++] = "\n";
4684                 }
4685         }
4686
4687         // replace spaces in the cachename with _ characters
4688         for (i = 0;cachename[i];i++)
4689                 if (cachename[i] == ' ')
4690                         cachename[i] = '_';
4691
4692         // now append the shader text itself
4693         vertstrings_list[vertstrings_count++] = vertexstring;
4694         geomstrings_list[geomstrings_count++] = geometrystring;
4695         fragstrings_list[fragstrings_count++] = fragmentstring;
4696
4697         // if any sources were NULL, clear the respective list
4698         if (!vertexstring)
4699                 vertstrings_count = 0;
4700         if (!geometrystring)
4701                 geomstrings_count = 0;
4702         if (!fragmentstring)
4703                 fragstrings_count = 0;
4704
4705         vertstring_length = 0;
4706         for (i = 0;i < vertstrings_count;i++)
4707                 vertstring_length += strlen(vertstrings_list[i]);
4708         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4709         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4710                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4711
4712         geomstring_length = 0;
4713         for (i = 0;i < geomstrings_count;i++)
4714                 geomstring_length += strlen(geomstrings_list[i]);
4715         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4716         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4717                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4718
4719         fragstring_length = 0;
4720         for (i = 0;i < fragstrings_count;i++)
4721                 fragstring_length += strlen(fragstrings_list[i]);
4722         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4723         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4724                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4725
4726         // try to load the cached shader, or generate one
4727         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4728
4729         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4730                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4731         else
4732                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4733
4734         // free the strings
4735         if (vertstring)
4736                 Mem_Free(vertstring);
4737         if (geomstring)
4738                 Mem_Free(geomstring);
4739         if (fragstring)
4740                 Mem_Free(fragstring);
4741         if (vertexstring)
4742                 Mem_Free(vertexstring);
4743         if (geometrystring)
4744                 Mem_Free(geometrystring);
4745         if (fragmentstring)
4746                 Mem_Free(fragmentstring);
4747 }
4748
4749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4751 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);}
4752 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);}
4753 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);}
4754 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);}
4755
4756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4758 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);}
4759 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);}
4760 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);}
4761 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);}
4762
4763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4764 {
4765         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4766         if (r_hlsl_permutation != perm)
4767         {
4768                 r_hlsl_permutation = perm;
4769                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4770                 {
4771                         if (!r_hlsl_permutation->compiled)
4772                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4773                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4774                         {
4775                                 // remove features until we find a valid permutation
4776                                 int i;
4777                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4778                                 {
4779                                         // reduce i more quickly whenever it would not remove any bits
4780                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4781                                         if (!(permutation & j))
4782                                                 continue;
4783                                         permutation -= j;
4784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4785                                         if (!r_hlsl_permutation->compiled)
4786                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4787                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4788                                                 break;
4789                                 }
4790                                 if (i >= SHADERPERMUTATION_COUNT)
4791                                 {
4792                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4793                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4794                                         return; // no bit left to clear, entire mode is broken
4795                                 }
4796                         }
4797                 }
4798                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4799                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4800         }
4801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4803         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4804 }
4805 #endif
4806
4807 void R_GLSL_Restart_f(void)
4808 {
4809         unsigned int i, limit;
4810         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4811                 Mem_Free(glslshaderstring);
4812         glslshaderstring = NULL;
4813         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4814                 Mem_Free(cgshaderstring);
4815         cgshaderstring = NULL;
4816         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4817                 Mem_Free(hlslshaderstring);
4818         hlslshaderstring = NULL;
4819         switch(vid.renderpath)
4820         {
4821         case RENDERPATH_D3D9:
4822 #ifdef SUPPORTD3D
4823                 {
4824                         r_hlsl_permutation_t *p;
4825                         r_hlsl_permutation = NULL;
4826 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4827 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4828 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4829 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4830                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4831                         for (i = 0;i < limit;i++)
4832                         {
4833                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4834                                 {
4835                                         if (p->vertexshader)
4836                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4837                                         if (p->pixelshader)
4838                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4839                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4840                                 }
4841                         }
4842                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4843                 }
4844 #endif
4845                 break;
4846         case RENDERPATH_D3D10:
4847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4848                 break;
4849         case RENDERPATH_D3D11:
4850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4851                 break;
4852         case RENDERPATH_GL20:
4853                 {
4854                         r_glsl_permutation_t *p;
4855                         r_glsl_permutation = NULL;
4856                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4857                         for (i = 0;i < limit;i++)
4858                         {
4859                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4860                                 {
4861                                         GL_Backend_FreeProgram(p->program);
4862                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4863                                 }
4864                         }
4865                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4866                 }
4867                 break;
4868         case RENDERPATH_CGGL:
4869 #ifdef SUPPORTCG
4870                 {
4871                         r_cg_permutation_t *p;
4872                         r_cg_permutation = NULL;
4873                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4874                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4875                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4876                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4877                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4878                         for (i = 0;i < limit;i++)
4879                         {
4880                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4881                                 {
4882                                         if (p->vprogram)
4883                                                 cgDestroyProgram(p->vprogram);
4884                                         if (p->fprogram)
4885                                                 cgDestroyProgram(p->fprogram);
4886                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4887                                 }
4888                         }
4889                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4890                 }
4891 #endif
4892                 break;
4893         case RENDERPATH_GL13:
4894         case RENDERPATH_GL11:
4895                 break;
4896         }
4897 }
4898
4899 void R_GLSL_DumpShader_f(void)
4900 {
4901         int i;
4902         qfile_t *file;
4903
4904         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4905         if (file)
4906         {
4907                 FS_Print(file, "/* The engine may define the following macros:\n");
4908                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4909                 for (i = 0;i < SHADERMODE_COUNT;i++)
4910                         FS_Print(file, glslshadermodeinfo[i].pretext);
4911                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4912                         FS_Print(file, shaderpermutationinfo[i].pretext);
4913                 FS_Print(file, "*/\n");
4914                 FS_Print(file, builtinshaderstring);
4915                 FS_Close(file);
4916                 Con_Printf("glsl/default.glsl written\n");
4917         }
4918         else
4919                 Con_Printf("failed to write to glsl/default.glsl\n");
4920
4921 #ifdef SUPPORTCG
4922         file = FS_OpenRealFile("cg/default.cg", "w", false);
4923         if (file)
4924         {
4925                 FS_Print(file, "/* The engine may define the following macros:\n");
4926                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4927                 for (i = 0;i < SHADERMODE_COUNT;i++)
4928                         FS_Print(file, cgshadermodeinfo[i].pretext);
4929                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4930                         FS_Print(file, shaderpermutationinfo[i].pretext);
4931                 FS_Print(file, "*/\n");
4932                 FS_Print(file, builtincgshaderstring);
4933                 FS_Close(file);
4934                 Con_Printf("cg/default.cg written\n");
4935         }
4936         else
4937                 Con_Printf("failed to write to cg/default.cg\n");
4938 #endif
4939
4940 #ifdef SUPPORTD3D
4941         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4942         if (file)
4943         {
4944                 FS_Print(file, "/* The engine may define the following macros:\n");
4945                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4946                 for (i = 0;i < SHADERMODE_COUNT;i++)
4947                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4948                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4949                         FS_Print(file, shaderpermutationinfo[i].pretext);
4950                 FS_Print(file, "*/\n");
4951                 FS_Print(file, builtincgshaderstring);
4952                 FS_Close(file);
4953                 Con_Printf("hlsl/default.hlsl written\n");
4954         }
4955         else
4956                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4957 #endif
4958 }
4959
4960 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4961 {
4962         if (!second)
4963                 texturemode = GL_MODULATE;
4964         switch (vid.renderpath)
4965         {
4966         case RENDERPATH_D3D9:
4967 #ifdef SUPPORTD3D
4968                 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))));
4969                 R_Mesh_TexBind(GL20TU_FIRST , first );
4970                 R_Mesh_TexBind(GL20TU_SECOND, second);
4971 #endif
4972                 break;
4973         case RENDERPATH_D3D10:
4974                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4975                 break;
4976         case RENDERPATH_D3D11:
4977                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4978                 break;
4979         case RENDERPATH_GL20:
4980                 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))));
4981                 R_Mesh_TexBind(GL20TU_FIRST , first );
4982                 R_Mesh_TexBind(GL20TU_SECOND, second);
4983                 break;
4984         case RENDERPATH_CGGL:
4985 #ifdef SUPPORTCG
4986                 CHECKCGERROR
4987                 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))));
4988                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4989                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4990 #endif
4991                 break;
4992         case RENDERPATH_GL13:
4993                 R_Mesh_TexBind(0, first );
4994                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4995                 R_Mesh_TexBind(1, second);
4996                 if (second)
4997                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4998                 break;
4999         case RENDERPATH_GL11:
5000                 R_Mesh_TexBind(0, first );
5001                 break;
5002         }
5003 }
5004
5005 void R_SetupShader_DepthOrShadow(void)
5006 {
5007         switch (vid.renderpath)
5008         {
5009         case RENDERPATH_D3D9:
5010 #ifdef SUPPORTD3D
5011                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5012 #endif
5013                 break;
5014         case RENDERPATH_D3D10:
5015                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5016                 break;
5017         case RENDERPATH_D3D11:
5018                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5019                 break;
5020         case RENDERPATH_GL20:
5021                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5022                 break;
5023         case RENDERPATH_CGGL:
5024 #ifdef SUPPORTCG
5025                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5026 #endif
5027                 break;
5028         case RENDERPATH_GL13:
5029                 R_Mesh_TexBind(0, 0);
5030                 R_Mesh_TexBind(1, 0);
5031                 break;
5032         case RENDERPATH_GL11:
5033                 R_Mesh_TexBind(0, 0);
5034                 break;
5035         }
5036 }
5037
5038 void R_SetupShader_ShowDepth(void)
5039 {
5040         switch (vid.renderpath)
5041         {
5042         case RENDERPATH_D3D9:
5043 #ifdef SUPPORTHLSL
5044                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5045 #endif
5046                 break;
5047         case RENDERPATH_D3D10:
5048                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5049                 break;
5050         case RENDERPATH_D3D11:
5051                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5052                 break;
5053         case RENDERPATH_GL20:
5054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5055                 break;
5056         case RENDERPATH_CGGL:
5057 #ifdef SUPPORTCG
5058                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5059 #endif
5060                 break;
5061         case RENDERPATH_GL13:
5062                 break;
5063         case RENDERPATH_GL11:
5064                 break;
5065         }
5066 }
5067
5068 extern qboolean r_shadow_usingdeferredprepass;
5069 extern cvar_t r_shadow_deferred_8bitrange;
5070 extern rtexture_t *r_shadow_attenuationgradienttexture;
5071 extern rtexture_t *r_shadow_attenuation2dtexture;
5072 extern rtexture_t *r_shadow_attenuation3dtexture;
5073 extern qboolean r_shadow_usingshadowmap2d;
5074 extern qboolean r_shadow_usingshadowmaportho;
5075 extern float r_shadow_shadowmap_texturescale[2];
5076 extern float r_shadow_shadowmap_parameters[4];
5077 extern qboolean r_shadow_shadowmapvsdct;
5078 extern qboolean r_shadow_shadowmapsampler;
5079 extern int r_shadow_shadowmappcf;
5080 extern rtexture_t *r_shadow_shadowmap2dtexture;
5081 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5082 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5083 extern matrix4x4_t r_shadow_shadowmapmatrix;
5084 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5085 extern int r_shadow_prepass_width;
5086 extern int r_shadow_prepass_height;
5087 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5088 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5089 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5090 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5091 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5092 extern cvar_t gl_mesh_separatearrays;
5093 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5094 {
5095         // a blendfunc allows colormod if:
5096         // a) it can never keep the destination pixel invariant, or
5097         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5098         // this is to prevent unintended side effects from colormod
5099
5100         // in formulas:
5101         // IF there is a (s, sa) for which for all (d, da),
5102         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5103         // THEN, for this (s, sa) and all (colormod, d, da):
5104         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5105         // OBVIOUSLY, this means that
5106         //   s*colormod * src(s*colormod, d, sa, da) = 0
5107         //   dst(s*colormod, d, sa, da)              = 1
5108
5109         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5110
5111         // main condition to leave dst color invariant:
5112         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5113         //   src == GL_ZERO:
5114         //     s * 0 + d * dst(s, d, sa, da) == d
5115         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5116         //       => colormod is a problem for GL_SRC_COLOR only
5117         //   src == GL_ONE:
5118         //     s + d * dst(s, d, sa, da) == d
5119         //       => s == 0
5120         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5121         //       => colormod is never problematic for these
5122         //   src == GL_SRC_COLOR:
5123         //     s*s + d * dst(s, d, sa, da) == d
5124         //       => s == 0
5125         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5126         //       => colormod is never problematic for these
5127         //   src == GL_ONE_MINUS_SRC_COLOR:
5128         //     s*(1-s) + d * dst(s, d, sa, da) == d
5129         //       => s == 0 or s == 1
5130         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5131         //       => colormod is a problem for GL_SRC_COLOR only
5132         //   src == GL_DST_COLOR
5133         //     s*d + d * dst(s, d, sa, da) == d
5134         //       => s == 1
5135         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5136         //       => colormod is always a problem
5137         //     or
5138         //       => s == 0
5139         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5140         //       => colormod is never problematic for these
5141         //       => BUT, we do not know s! We must assume it is problematic
5142         //       then... except in GL_ONE case, where we know all invariant
5143         //       cases are fine
5144         //   src == GL_ONE_MINUS_DST_COLOR
5145         //     s*(1-d) + d * dst(s, d, sa, da) == d
5146         //       => s == 0 (1-d is impossible to handle for our desired result)
5147         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5148         //       => colormod is never problematic for these
5149         //   src == GL_SRC_ALPHA
5150         //     s*sa + d * dst(s, d, sa, da) == d
5151         //       => s == 0, or sa == 0
5152         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5153         //       => colormod breaks in the case GL_SRC_COLOR only
5154         //   src == GL_ONE_MINUS_SRC_ALPHA
5155         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5156         //       => s == 0, or sa == 1
5157         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5158         //       => colormod breaks in the case GL_SRC_COLOR only
5159         //   src == GL_DST_ALPHA
5160         //     s*da + d * dst(s, d, sa, da) == d
5161         //       => s == 0
5162         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5163         //       => colormod is never problematic for these
5164
5165         switch(src)
5166         {
5167                 case GL_ZERO:
5168                 case GL_ONE_MINUS_SRC_COLOR:
5169                 case GL_SRC_ALPHA:
5170                 case GL_ONE_MINUS_SRC_ALPHA:
5171                         if(dst == GL_SRC_COLOR)
5172                                 return false;
5173                         return true;
5174                 case GL_ONE:
5175                 case GL_SRC_COLOR:
5176                 case GL_ONE_MINUS_DST_COLOR:
5177                 case GL_DST_ALPHA:
5178                 case GL_ONE_MINUS_DST_ALPHA:
5179                         return true;
5180                 case GL_DST_COLOR:
5181                         if(dst == GL_ONE)
5182                                 return true;
5183                         return false;
5184                 default:
5185                         return false;
5186         }
5187 }
5188 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)
5189 {
5190         // select a permutation of the lighting shader appropriate to this
5191         // combination of texture, entity, light source, and fogging, only use the
5192         // minimum features necessary to avoid wasting rendering time in the
5193         // fragment shader on features that are not being used
5194         unsigned int permutation = 0;
5195         unsigned int mode = 0;
5196         qboolean allow_colormod;
5197         static float dummy_colormod[3] = {1, 1, 1};
5198         float *colormod = rsurface.colormod;
5199         float m16f[16];
5200         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5201         if (rsurfacepass == RSURFPASS_BACKGROUND)
5202         {
5203                 // distorted background
5204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5205                         mode = SHADERMODE_WATER;
5206                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5207                         mode = SHADERMODE_REFRACTION;
5208                 else
5209                 {
5210                         mode = SHADERMODE_GENERIC;
5211                         permutation |= SHADERPERMUTATION_DIFFUSE;
5212                 }
5213                 GL_AlphaTest(false);
5214                 GL_BlendFunc(GL_ONE, GL_ZERO);
5215                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5216         }
5217         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5218         {
5219                 if (r_glsl_offsetmapping.integer)
5220                 {
5221                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5222                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5223                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5224                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5225                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5226                         {
5227                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5228                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5229                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5230                         }
5231                 }
5232                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5233                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5235                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5236                 // normalmap (deferred prepass), may use alpha test on diffuse
5237                 mode = SHADERMODE_DEFERREDGEOMETRY;
5238                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5239                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5240                 GL_AlphaTest(false);
5241                 GL_BlendFunc(GL_ONE, GL_ZERO);
5242                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5243         }
5244         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5245         {
5246                 if (r_glsl_offsetmapping.integer)
5247                 {
5248                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5249                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5250                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5251                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5252                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5253                         {
5254                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5255                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5256                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5257                         }
5258                 }
5259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5261                 // light source
5262                 mode = SHADERMODE_LIGHTSOURCE;
5263                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5264                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5265                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5266                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5267                 if (diffusescale > 0)
5268                         permutation |= SHADERPERMUTATION_DIFFUSE;
5269                 if (specularscale > 0)
5270                 {
5271                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5272                         if (r_shadow_glossexact.integer)
5273                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5274                 }
5275                 if (r_refdef.fogenabled)
5276                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5277                 if (rsurface.texture->colormapping)
5278                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5279                 if (r_shadow_usingshadowmap2d)
5280                 {
5281                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5282                         if(r_shadow_shadowmapvsdct)
5283                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5284
5285                         if (r_shadow_shadowmapsampler)
5286                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5287                         if (r_shadow_shadowmappcf > 1)
5288                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5289                         else if (r_shadow_shadowmappcf)
5290                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5291                 }
5292                 if (rsurface.texture->reflectmasktexture)
5293                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5294                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5295                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5296                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5297         }
5298         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5299         {
5300                 if (r_glsl_offsetmapping.integer)
5301                 {
5302                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5303                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5304                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5305                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5306                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5307                         {
5308                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5309                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5310                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5311                         }
5312                 }
5313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5314                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5315                 // unshaded geometry (fullbright or ambient model lighting)
5316                 mode = SHADERMODE_FLATCOLOR;
5317                 ambientscale = diffusescale = specularscale = 0;
5318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5319                         permutation |= SHADERPERMUTATION_GLOW;
5320                 if (r_refdef.fogenabled)
5321                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5322                 if (rsurface.texture->colormapping)
5323                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5324                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5325                 {
5326                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5327                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5328
5329                         if (r_shadow_shadowmapsampler)
5330                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5331                         if (r_shadow_shadowmappcf > 1)
5332                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5333                         else if (r_shadow_shadowmappcf)
5334                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5335                 }
5336                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5337                         permutation |= SHADERPERMUTATION_REFLECTION;
5338                 if (rsurface.texture->reflectmasktexture)
5339                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5340                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5342                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5343         }
5344         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5345         {
5346                 if (r_glsl_offsetmapping.integer)
5347                 {
5348                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5349                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5350                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5351                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5352                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5353                         {
5354                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5355                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5356                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5357                         }
5358                 }
5359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5360                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5361                 // directional model lighting
5362                 mode = SHADERMODE_LIGHTDIRECTION;
5363                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5364                         permutation |= SHADERPERMUTATION_GLOW;
5365                 permutation |= SHADERPERMUTATION_DIFFUSE;
5366                 if (specularscale > 0)
5367                 {
5368                         permutation |= SHADERPERMUTATION_SPECULAR;
5369                         if (r_shadow_glossexact.integer)
5370                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5371                 }
5372                 if (r_refdef.fogenabled)
5373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5374                 if (rsurface.texture->colormapping)
5375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5377                 {
5378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5380
5381                         if (r_shadow_shadowmapsampler)
5382                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5383                         if (r_shadow_shadowmappcf > 1)
5384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5385                         else if (r_shadow_shadowmappcf)
5386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5387                 }
5388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5389                         permutation |= SHADERPERMUTATION_REFLECTION;
5390                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5391                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5392                 if (rsurface.texture->reflectmasktexture)
5393                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5394                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5395                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5396                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5397         }
5398         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5399         {
5400                 if (r_glsl_offsetmapping.integer)
5401                 {
5402                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5403                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5404                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5405                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5406                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5407                         {
5408                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5409                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5410                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5411                         }
5412                 }
5413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5415                 // ambient model lighting
5416                 mode = SHADERMODE_LIGHTDIRECTION;
5417                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5418                         permutation |= SHADERPERMUTATION_GLOW;
5419                 if (r_refdef.fogenabled)
5420                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5421                 if (rsurface.texture->colormapping)
5422                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5423                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5424                 {
5425                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5426                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5427
5428                         if (r_shadow_shadowmapsampler)
5429                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5430                         if (r_shadow_shadowmappcf > 1)
5431                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5432                         else if (r_shadow_shadowmappcf)
5433                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5434                 }
5435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5436                         permutation |= SHADERPERMUTATION_REFLECTION;
5437                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5438                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5439                 if (rsurface.texture->reflectmasktexture)
5440                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5441                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5442                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5443                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5444         }
5445         else
5446         {
5447                 if (r_glsl_offsetmapping.integer)
5448                 {
5449                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5450                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5451                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5452                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5453                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5454                         {
5455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5456                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5457                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5458                         }
5459                 }
5460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5462                 // lightmapped wall
5463                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5464                         permutation |= SHADERPERMUTATION_GLOW;
5465                 if (r_refdef.fogenabled)
5466                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5467                 if (rsurface.texture->colormapping)
5468                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5469                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5470                 {
5471                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5472                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5473
5474                         if (r_shadow_shadowmapsampler)
5475                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5476                         if (r_shadow_shadowmappcf > 1)
5477                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5478                         else if (r_shadow_shadowmappcf)
5479                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5480                 }
5481                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5482                         permutation |= SHADERPERMUTATION_REFLECTION;
5483                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5484                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5485                 if (rsurface.texture->reflectmasktexture)
5486                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5487                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5488                 {
5489                         // deluxemapping (light direction texture)
5490                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5491                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5492                         else
5493                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5494                         permutation |= SHADERPERMUTATION_DIFFUSE;
5495                         if (specularscale > 0)
5496                         {
5497                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5498                                 if (r_shadow_glossexact.integer)
5499                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5500                         }
5501                 }
5502                 else if (r_glsl_deluxemapping.integer >= 2)
5503                 {
5504                         // fake deluxemapping (uniform light direction in tangentspace)
5505                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5506                         permutation |= SHADERPERMUTATION_DIFFUSE;
5507                         if (specularscale > 0)
5508                         {
5509                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5510                                 if (r_shadow_glossexact.integer)
5511                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5512                         }
5513                 }
5514                 else if (rsurface.uselightmaptexture)
5515                 {
5516                         // ordinary lightmapping (q1bsp, q3bsp)
5517                         mode = SHADERMODE_LIGHTMAP;
5518                 }
5519                 else
5520                 {
5521                         // ordinary vertex coloring (q3bsp)
5522                         mode = SHADERMODE_VERTEXCOLOR;
5523                 }
5524                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5525                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5526                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5527         }
5528         if(!allow_colormod)
5529                 colormod = dummy_colormod;
5530         switch(vid.renderpath)
5531         {
5532         case RENDERPATH_D3D9:
5533 #ifdef SUPPORTD3D
5534                 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);
5535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5538                 if (mode == SHADERMODE_LIGHTSOURCE)
5539                 {
5540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5542                 }
5543                 else
5544                 {
5545                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5546                         {
5547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5548                         }
5549                 }
5550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5555
5556                 if (mode == SHADERMODE_LIGHTSOURCE)
5557                 {
5558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5563
5564                         // additive passes are only darkened by fog, not tinted
5565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5567                 }
5568                 else
5569                 {
5570                         if (mode == SHADERMODE_FLATCOLOR)
5571                         {
5572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5573                         }
5574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5575                         {
5576                                 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]);
5577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5578                                 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);
5579                                 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);
5580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5583                         }
5584                         else
5585                         {
5586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5588                                 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);
5589                                 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);
5590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5591                         }
5592                         // additive passes are only darkened by fog, not tinted
5593                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5595                         else
5596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5597                         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);
5598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5600                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5601                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5605                 }
5606                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5607                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5608                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5609                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5610                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5611                 if (rsurface.texture->pantstexture)
5612                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5613                 else
5614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5615                 if (rsurface.texture->shirttexture)
5616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5617                 else
5618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5619                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5620                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5621                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5622                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5623                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5624                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5625                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5626
5627                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5628                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5629                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5630                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5634                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5635                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5636                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5637                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5638                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5639                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5640                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5641                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5642                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5643                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5644                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5645                 {
5646                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5647                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5648                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5649                 }
5650                 else
5651                 {
5652                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5653                 }
5654 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5655 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5656                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5657                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5658                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5659                 {
5660                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5661                         if (rsurface.rtlight)
5662                         {
5663                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5664                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5665                         }
5666                 }
5667 #endif
5668                 break;
5669         case RENDERPATH_D3D10:
5670                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5671                 break;
5672         case RENDERPATH_D3D11:
5673                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5674                 break;
5675         case RENDERPATH_GL20:
5676                 if (gl_mesh_separatearrays.integer)
5677                 {
5678                         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);
5679                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5680                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5681                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5682                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5683                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5684                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5685                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5686                 }
5687                 else
5688                 {
5689                         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);
5690                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5691                 }
5692                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5693                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5694                 if (mode == SHADERMODE_LIGHTSOURCE)
5695                 {
5696                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5697                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5698                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5699                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5700                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5701                         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);
5702         
5703                         // additive passes are only darkened by fog, not tinted
5704                         if (r_glsl_permutation->loc_FogColor >= 0)
5705                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5706                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5707                 }
5708                 else
5709                 {
5710                         if (mode == SHADERMODE_FLATCOLOR)
5711                         {
5712                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5713                         }
5714                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5715                         {
5716                                 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]);
5717                                 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]);
5718                                 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);
5719                                 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);
5720                                 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);
5721                                 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]);
5722                                 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]);
5723                         }
5724                         else
5725                         {
5726                                 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]);
5727                                 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]);
5728                                 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);
5729                                 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);
5730                                 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);
5731                         }
5732                         // additive passes are only darkened by fog, not tinted
5733                         if (r_glsl_permutation->loc_FogColor >= 0)
5734                         {
5735                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5736                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5737                                 else
5738                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5739                         }
5740                         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);
5741                         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]);
5742                         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]);
5743                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5744                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5745                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5746                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5747                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5748                 }
5749                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5750                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5751                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5752                 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]);
5753                 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]);
5754
5755                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5756                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5757                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5758                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5759                 {
5760                         if (rsurface.texture->pantstexture)
5761                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5762                         else
5763                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5764                 }
5765                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5766                 {
5767                         if (rsurface.texture->shirttexture)
5768                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5769                         else
5770                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5771                 }
5772                 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]);
5773                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5774                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5775                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5776                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5777                 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]);
5778                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5779
5780         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5781         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5782         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5783                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5784                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5785                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5786                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5787                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5788                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5789                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5790                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5791                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5792                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5793                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5794                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5795                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5796                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5797                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5798                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5799                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5800                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5801                 {
5802                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5803                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5804                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5805                 }
5806                 else
5807                 {
5808                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5809                 }
5810 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5811 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5812                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5813                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5814                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5815                 {
5816                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5817                         if (rsurface.rtlight)
5818                         {
5819                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5820                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5821                         }
5822                 }
5823                 CHECKGLERROR
5824                 break;
5825         case RENDERPATH_CGGL:
5826 #ifdef SUPPORTCG
5827                 if (gl_mesh_separatearrays.integer)
5828                 {
5829                         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);
5830                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5831                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5832                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5833                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5834                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5835                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5836                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5837                 }
5838                 else
5839                 {
5840                         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);
5841                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5842                 }
5843                 R_SetupShader_SetPermutationCG(mode, permutation);
5844                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5845                 if (mode == SHADERMODE_LIGHTSOURCE)
5846                 {
5847                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5848                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5849                 }
5850                 else
5851                 {
5852                         if (mode == SHADERMODE_LIGHTDIRECTION)
5853                         {
5854                                 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
5855                         }
5856                 }
5857                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5858                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5859                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5860                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5861                 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
5862                 CHECKGLERROR
5863
5864                 if (mode == SHADERMODE_LIGHTSOURCE)
5865                 {
5866                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5867                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5868                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5869                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5870                         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
5871
5872                         // additive passes are only darkened by fog, not tinted
5873                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5874                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5875                 }
5876                 else
5877                 {
5878                         if (mode == SHADERMODE_FLATCOLOR)
5879                         {
5880                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5881                         }
5882                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5883                         {
5884                                 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
5885                                 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
5886                                 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
5887                                 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
5888                                 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
5889                                 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
5890                                 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
5891                         }
5892                         else
5893                         {
5894                                 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
5895                                 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
5896                                 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
5897                                 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
5898                                 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
5899                         }
5900                         // additive passes are only darkened by fog, not tinted
5901                         if (r_cg_permutation->fp_FogColor)
5902                         {
5903                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5904                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5905                                 else
5906                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5907                                 CHECKCGERROR
5908                         }
5909                         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
5910                         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
5911                         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
5912                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5913                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5914                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5915                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5916                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5917                 }
5918                 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
5919                 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
5920                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5921                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5922                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5923                 if (r_cg_permutation->fp_Color_Pants)
5924                 {
5925                         if (rsurface.texture->pantstexture)
5926                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5927                         else
5928                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5929                         CHECKCGERROR
5930                 }
5931                 if (r_cg_permutation->fp_Color_Shirt)
5932                 {
5933                         if (rsurface.texture->shirttexture)
5934                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5935                         else
5936                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5937                         CHECKCGERROR
5938                 }
5939                 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
5940                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5941                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5942                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5943                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5944                 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
5945                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5946
5947         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5948         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5949         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5950                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5951                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5952                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5953                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5954                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5955                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5956                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5957                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5958                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5959                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5960                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5961                 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
5962                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5963                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5964                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5965                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5966                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5967                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5968                 {
5969                         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
5970                         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
5971                         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
5972                 }
5973                 else
5974                 {
5975                         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
5976                 }
5977                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5978                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5979                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5980                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5981                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5982                 {
5983                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5984                         if (rsurface.rtlight)
5985                         {
5986                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5987                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5988                         }
5989                 }
5990
5991                 CHECKGLERROR
5992 #endif
5993                 break;
5994         case RENDERPATH_GL13:
5995         case RENDERPATH_GL11:
5996                 break;
5997         }
5998 }
5999
6000 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6001 {
6002         // select a permutation of the lighting shader appropriate to this
6003         // combination of texture, entity, light source, and fogging, only use the
6004         // minimum features necessary to avoid wasting rendering time in the
6005         // fragment shader on features that are not being used
6006         unsigned int permutation = 0;
6007         unsigned int mode = 0;
6008         const float *lightcolorbase = rtlight->currentcolor;
6009         float ambientscale = rtlight->ambientscale;
6010         float diffusescale = rtlight->diffusescale;
6011         float specularscale = rtlight->specularscale;
6012         // this is the location of the light in view space
6013         vec3_t viewlightorigin;
6014         // this transforms from view space (camera) to light space (cubemap)
6015         matrix4x4_t viewtolight;
6016         matrix4x4_t lighttoview;
6017         float viewtolight16f[16];
6018         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6019         // light source
6020         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6021         if (rtlight->currentcubemap != r_texture_whitecube)
6022                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6023         if (diffusescale > 0)
6024                 permutation |= SHADERPERMUTATION_DIFFUSE;
6025         if (specularscale > 0)
6026         {
6027                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6028                 if (r_shadow_glossexact.integer)
6029                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6030         }
6031         if (r_shadow_usingshadowmap2d)
6032         {
6033                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6034                 if (r_shadow_shadowmapvsdct)
6035                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6036
6037                 if (r_shadow_shadowmapsampler)
6038                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6039                 if (r_shadow_shadowmappcf > 1)
6040                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6041                 else if (r_shadow_shadowmappcf)
6042                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6043         }
6044         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6045         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6046         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6047         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6048         switch(vid.renderpath)
6049         {
6050         case RENDERPATH_D3D9:
6051 #ifdef SUPPORTD3D
6052                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6053                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6054                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6055                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6056                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6057                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6058                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6059                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6060                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6061                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6062                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6063
6064                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6065                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6066                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6067                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6068                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6069                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6070 #endif
6071                 break;
6072         case RENDERPATH_D3D10:
6073                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6074                 break;
6075         case RENDERPATH_D3D11:
6076                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6077                 break;
6078         case RENDERPATH_GL20:
6079                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6080                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6081                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6082                 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);
6083                 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);
6084                 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);
6085                 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]);
6086                 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]);
6087                 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));
6088                 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]);
6089                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6090
6091                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6092                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6093                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6094                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6095                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6096                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6097                 break;
6098         case RENDERPATH_CGGL:
6099 #ifdef SUPPORTCG
6100                 R_SetupShader_SetPermutationCG(mode, permutation);
6101                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6102                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6103                 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
6104                 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
6105                 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
6106                 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
6107                 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
6108                 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
6109                 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
6110                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6111
6112                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6113                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6114                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6115                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6116                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6117                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6118 #endif
6119                 break;
6120         case RENDERPATH_GL13:
6121         case RENDERPATH_GL11:
6122                 break;
6123         }
6124 }
6125
6126 #define SKINFRAME_HASH 1024
6127
6128 typedef struct
6129 {
6130         int loadsequence; // incremented each level change
6131         memexpandablearray_t array;
6132         skinframe_t *hash[SKINFRAME_HASH];
6133 }
6134 r_skinframe_t;
6135 r_skinframe_t r_skinframe;
6136
6137 void R_SkinFrame_PrepareForPurge(void)
6138 {
6139         r_skinframe.loadsequence++;
6140         // wrap it without hitting zero
6141         if (r_skinframe.loadsequence >= 200)
6142                 r_skinframe.loadsequence = 1;
6143 }
6144
6145 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6146 {
6147         if (!skinframe)
6148                 return;
6149         // mark the skinframe as used for the purging code
6150         skinframe->loadsequence = r_skinframe.loadsequence;
6151 }
6152
6153 void R_SkinFrame_Purge(void)
6154 {
6155         int i;
6156         skinframe_t *s;
6157         for (i = 0;i < SKINFRAME_HASH;i++)
6158         {
6159                 for (s = r_skinframe.hash[i];s;s = s->next)
6160                 {
6161                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6162                         {
6163                                 if (s->merged == s->base)
6164                                         s->merged = NULL;
6165                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6166                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6167                                 R_PurgeTexture(s->merged);s->merged = NULL;
6168                                 R_PurgeTexture(s->base  );s->base   = NULL;
6169                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6170                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6171                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6172                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6173                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6174                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6175                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6176                                 s->loadsequence = 0;
6177                         }
6178                 }
6179         }
6180 }
6181
6182 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6183         skinframe_t *item;
6184         char basename[MAX_QPATH];
6185
6186         Image_StripImageExtension(name, basename, sizeof(basename));
6187
6188         if( last == NULL ) {
6189                 int hashindex;
6190                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6191                 item = r_skinframe.hash[hashindex];
6192         } else {
6193                 item = last->next;
6194         }
6195
6196         // linearly search through the hash bucket
6197         for( ; item ; item = item->next ) {
6198                 if( !strcmp( item->basename, basename ) ) {
6199                         return item;
6200                 }
6201         }
6202         return NULL;
6203 }
6204
6205 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6206 {
6207         skinframe_t *item;
6208         int hashindex;
6209         char basename[MAX_QPATH];
6210
6211         Image_StripImageExtension(name, basename, sizeof(basename));
6212
6213         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6214         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6215                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6216                         break;
6217
6218         if (!item) {
6219                 rtexture_t *dyntexture;
6220                 // check whether its a dynamic texture
6221                 dyntexture = CL_GetDynTexture( basename );
6222                 if (!add && !dyntexture)
6223                         return NULL;
6224                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6225                 memset(item, 0, sizeof(*item));
6226                 strlcpy(item->basename, basename, sizeof(item->basename));
6227                 item->base = dyntexture; // either NULL or dyntexture handle
6228                 item->textureflags = textureflags;
6229                 item->comparewidth = comparewidth;
6230                 item->compareheight = compareheight;
6231                 item->comparecrc = comparecrc;
6232                 item->next = r_skinframe.hash[hashindex];
6233                 r_skinframe.hash[hashindex] = item;
6234         }
6235         else if( item->base == NULL )
6236         {
6237                 rtexture_t *dyntexture;
6238                 // check whether its a dynamic texture
6239                 // 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]
6240                 dyntexture = CL_GetDynTexture( basename );
6241                 item->base = dyntexture; // either NULL or dyntexture handle
6242         }
6243
6244         R_SkinFrame_MarkUsed(item);
6245         return item;
6246 }
6247
6248 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6249         { \
6250                 unsigned long long avgcolor[5], wsum; \
6251                 int pix, comp, w; \
6252                 avgcolor[0] = 0; \
6253                 avgcolor[1] = 0; \
6254                 avgcolor[2] = 0; \
6255                 avgcolor[3] = 0; \
6256                 avgcolor[4] = 0; \
6257                 wsum = 0; \
6258                 for(pix = 0; pix < cnt; ++pix) \
6259                 { \
6260                         w = 0; \
6261                         for(comp = 0; comp < 3; ++comp) \
6262                                 w += getpixel; \
6263                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6264                         { \
6265                                 ++wsum; \
6266                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6267                                 w = getpixel; \
6268                                 for(comp = 0; comp < 3; ++comp) \
6269                                         avgcolor[comp] += getpixel * w; \
6270                                 avgcolor[3] += w; \
6271                         } \
6272                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6273                         avgcolor[4] += getpixel; \
6274                 } \
6275                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6276                         avgcolor[3] = 1; \
6277                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6278                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6279                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6280                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6281         }
6282
6283 extern cvar_t gl_picmip;
6284 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6285 {
6286         int j;
6287         unsigned char *pixels;
6288         unsigned char *bumppixels;
6289         unsigned char *basepixels = NULL;
6290         int basepixels_width = 0;
6291         int basepixels_height = 0;
6292         skinframe_t *skinframe;
6293         rtexture_t *ddsbase = NULL;
6294         qboolean ddshasalpha = false;
6295         float ddsavgcolor[4];
6296         char basename[MAX_QPATH];
6297         int miplevel = R_PicmipForFlags(textureflags);
6298         int savemiplevel = miplevel;
6299         int mymiplevel;
6300
6301         if (cls.state == ca_dedicated)
6302                 return NULL;
6303
6304         // return an existing skinframe if already loaded
6305         // if loading of the first image fails, don't make a new skinframe as it
6306         // would cause all future lookups of this to be missing
6307         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6308         if (skinframe && skinframe->base)
6309                 return skinframe;
6310
6311         Image_StripImageExtension(name, basename, sizeof(basename));
6312
6313         // check for DDS texture file first
6314         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6315         {
6316                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6317                 if (basepixels == NULL)
6318                         return NULL;
6319         }
6320
6321         // FIXME handle miplevel
6322
6323         if (developer_loading.integer)
6324                 Con_Printf("loading skin \"%s\"\n", name);
6325
6326         // we've got some pixels to store, so really allocate this new texture now
6327         if (!skinframe)
6328                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6329         skinframe->stain = NULL;
6330         skinframe->merged = NULL;
6331         skinframe->base = NULL;
6332         skinframe->pants = NULL;
6333         skinframe->shirt = NULL;
6334         skinframe->nmap = NULL;
6335         skinframe->gloss = NULL;
6336         skinframe->glow = NULL;
6337         skinframe->fog = NULL;
6338         skinframe->reflect = NULL;
6339         skinframe->hasalpha = false;
6340
6341         if (ddsbase)
6342         {
6343                 skinframe->base = ddsbase;
6344                 skinframe->hasalpha = ddshasalpha;
6345                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6346                 if (r_loadfog && skinframe->hasalpha)
6347                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6348                 //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]);
6349         }
6350         else
6351         {
6352                 basepixels_width = image_width;
6353                 basepixels_height = image_height;
6354                 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);
6355                 if (textureflags & TEXF_ALPHA)
6356                 {
6357                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6358                         {
6359                                 if (basepixels[j] < 255)
6360                                 {
6361                                         skinframe->hasalpha = true;
6362                                         break;
6363                                 }
6364                         }
6365                         if (r_loadfog && skinframe->hasalpha)
6366                         {
6367                                 // has transparent pixels
6368                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6369                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6370                                 {
6371                                         pixels[j+0] = 255;
6372                                         pixels[j+1] = 255;
6373                                         pixels[j+2] = 255;
6374                                         pixels[j+3] = basepixels[j+3];
6375                                 }
6376                                 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);
6377                                 Mem_Free(pixels);
6378                         }
6379                 }
6380                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6381                 //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]);
6382                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6383                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6385                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6386         }
6387
6388         if (r_loaddds)
6389         {
6390                 mymiplevel = savemiplevel;
6391                 if (r_loadnormalmap)
6392                         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);
6393                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6394                 if (r_loadgloss)
6395                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6396                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6397                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6398                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6399         }
6400
6401         // _norm is the name used by tenebrae and has been adopted as standard
6402         if (r_loadnormalmap && skinframe->nmap == NULL)
6403         {
6404                 mymiplevel = savemiplevel;
6405                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6406                 {
6407                         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);
6408                         Mem_Free(pixels);
6409                         pixels = NULL;
6410                 }
6411                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6412                 {
6413                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6414                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6415                         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);
6416                         Mem_Free(pixels);
6417                         Mem_Free(bumppixels);
6418                 }
6419                 else if (r_shadow_bumpscale_basetexture.value > 0)
6420                 {
6421                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6422                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6423                         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);
6424                         Mem_Free(pixels);
6425                 }
6426                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6427                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6428         }
6429
6430         // _luma is supported only for tenebrae compatibility
6431         // _glow is the preferred name
6432         mymiplevel = savemiplevel;
6433         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))))
6434         {
6435                 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);
6436                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6437                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6438                 Mem_Free(pixels);pixels = NULL;
6439         }
6440
6441         mymiplevel = savemiplevel;
6442         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6443         {
6444                 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);
6445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6446                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6447                 Mem_Free(pixels);
6448                 pixels = NULL;
6449         }
6450
6451         mymiplevel = savemiplevel;
6452         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6453         {
6454                 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);
6455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6456                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6457                 Mem_Free(pixels);
6458                 pixels = NULL;
6459         }
6460
6461         mymiplevel = savemiplevel;
6462         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6463         {
6464                 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);
6465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6466                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6467                 Mem_Free(pixels);
6468                 pixels = NULL;
6469         }
6470
6471         mymiplevel = savemiplevel;
6472         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6473         {
6474                 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);
6475                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6476                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6477                 Mem_Free(pixels);
6478                 pixels = NULL;
6479         }
6480
6481         if (basepixels)
6482                 Mem_Free(basepixels);
6483
6484         return skinframe;
6485 }
6486
6487 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6488 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6489 {
6490         int i;
6491         unsigned char *temp1, *temp2;
6492         skinframe_t *skinframe;
6493
6494         if (cls.state == ca_dedicated)
6495                 return NULL;
6496
6497         // if already loaded just return it, otherwise make a new skinframe
6498         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6499         if (skinframe && skinframe->base)
6500                 return skinframe;
6501
6502         skinframe->stain = NULL;
6503         skinframe->merged = NULL;
6504         skinframe->base = NULL;
6505         skinframe->pants = NULL;
6506         skinframe->shirt = NULL;
6507         skinframe->nmap = NULL;
6508         skinframe->gloss = NULL;
6509         skinframe->glow = NULL;
6510         skinframe->fog = NULL;
6511         skinframe->reflect = NULL;
6512         skinframe->hasalpha = false;
6513
6514         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6515         if (!skindata)
6516                 return NULL;
6517
6518         if (developer_loading.integer)
6519                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6520
6521         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6522         {
6523                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6524                 temp2 = temp1 + width * height * 4;
6525                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6526                 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);
6527                 Mem_Free(temp1);
6528         }
6529         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6530         if (textureflags & TEXF_ALPHA)
6531         {
6532                 for (i = 3;i < width * height * 4;i += 4)
6533                 {
6534                         if (skindata[i] < 255)
6535                         {
6536                                 skinframe->hasalpha = true;
6537                                 break;
6538                         }
6539                 }
6540                 if (r_loadfog && skinframe->hasalpha)
6541                 {
6542                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6543                         memcpy(fogpixels, skindata, width * height * 4);
6544                         for (i = 0;i < width * height * 4;i += 4)
6545                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6546                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6547                         Mem_Free(fogpixels);
6548                 }
6549         }
6550
6551         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6552         //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]);
6553
6554         return skinframe;
6555 }
6556
6557 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6558 {
6559         int i;
6560         int featuresmask;
6561         skinframe_t *skinframe;
6562
6563         if (cls.state == ca_dedicated)
6564                 return NULL;
6565
6566         // if already loaded just return it, otherwise make a new skinframe
6567         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6568         if (skinframe && skinframe->base)
6569                 return skinframe;
6570
6571         skinframe->stain = NULL;
6572         skinframe->merged = NULL;
6573         skinframe->base = NULL;
6574         skinframe->pants = NULL;
6575         skinframe->shirt = NULL;
6576         skinframe->nmap = NULL;
6577         skinframe->gloss = NULL;
6578         skinframe->glow = NULL;
6579         skinframe->fog = NULL;
6580         skinframe->reflect = NULL;
6581         skinframe->hasalpha = false;
6582
6583         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6584         if (!skindata)
6585                 return NULL;
6586
6587         if (developer_loading.integer)
6588                 Con_Printf("loading quake skin \"%s\"\n", name);
6589
6590         // 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)
6591         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6592         memcpy(skinframe->qpixels, skindata, width*height);
6593         skinframe->qwidth = width;
6594         skinframe->qheight = height;
6595
6596         featuresmask = 0;
6597         for (i = 0;i < width * height;i++)
6598                 featuresmask |= palette_featureflags[skindata[i]];
6599
6600         skinframe->hasalpha = false;
6601         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6602         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6603         skinframe->qgeneratemerged = true;
6604         skinframe->qgeneratebase = skinframe->qhascolormapping;
6605         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6606
6607         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6608         //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]);
6609
6610         return skinframe;
6611 }
6612
6613 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6614 {
6615         int width;
6616         int height;
6617         unsigned char *skindata;
6618
6619         if (!skinframe->qpixels)
6620                 return;
6621
6622         if (!skinframe->qhascolormapping)
6623                 colormapped = false;
6624
6625         if (colormapped)
6626         {
6627                 if (!skinframe->qgeneratebase)
6628                         return;
6629         }
6630         else
6631         {
6632                 if (!skinframe->qgeneratemerged)
6633                         return;
6634         }
6635
6636         width = skinframe->qwidth;
6637         height = skinframe->qheight;
6638         skindata = skinframe->qpixels;
6639
6640         if (skinframe->qgeneratenmap)
6641         {
6642                 unsigned char *temp1, *temp2;
6643                 skinframe->qgeneratenmap = false;
6644                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6645                 temp2 = temp1 + width * height * 4;
6646                 // use either a custom palette or the quake palette
6647                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6648                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6649                 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);
6650                 Mem_Free(temp1);
6651         }
6652
6653         if (skinframe->qgenerateglow)
6654         {
6655                 skinframe->qgenerateglow = false;
6656                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6657         }
6658
6659         if (colormapped)
6660         {
6661                 skinframe->qgeneratebase = false;
6662                 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);
6663                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6664                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6665         }
6666         else
6667         {
6668                 skinframe->qgeneratemerged = false;
6669                 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);
6670         }
6671
6672         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6673         {
6674                 Mem_Free(skinframe->qpixels);
6675                 skinframe->qpixels = NULL;
6676         }
6677 }
6678
6679 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)
6680 {
6681         int i;
6682         skinframe_t *skinframe;
6683
6684         if (cls.state == ca_dedicated)
6685                 return NULL;
6686
6687         // if already loaded just return it, otherwise make a new skinframe
6688         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6689         if (skinframe && skinframe->base)
6690                 return skinframe;
6691
6692         skinframe->stain = NULL;
6693         skinframe->merged = NULL;
6694         skinframe->base = NULL;
6695         skinframe->pants = NULL;
6696         skinframe->shirt = NULL;
6697         skinframe->nmap = NULL;
6698         skinframe->gloss = NULL;
6699         skinframe->glow = NULL;
6700         skinframe->fog = NULL;
6701         skinframe->reflect = NULL;
6702         skinframe->hasalpha = false;
6703
6704         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6705         if (!skindata)
6706                 return NULL;
6707
6708         if (developer_loading.integer)
6709                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6710
6711         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6712         if (textureflags & TEXF_ALPHA)
6713         {
6714                 for (i = 0;i < width * height;i++)
6715                 {
6716                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6717                         {
6718                                 skinframe->hasalpha = true;
6719                                 break;
6720                         }
6721                 }
6722                 if (r_loadfog && skinframe->hasalpha)
6723                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6724         }
6725
6726         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6727         //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]);
6728
6729         return skinframe;
6730 }
6731
6732 skinframe_t *R_SkinFrame_LoadMissing(void)
6733 {
6734         skinframe_t *skinframe;
6735
6736         if (cls.state == ca_dedicated)
6737                 return NULL;
6738
6739         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6740         skinframe->stain = NULL;
6741         skinframe->merged = NULL;
6742         skinframe->base = NULL;
6743         skinframe->pants = NULL;
6744         skinframe->shirt = NULL;
6745         skinframe->nmap = NULL;
6746         skinframe->gloss = NULL;
6747         skinframe->glow = NULL;
6748         skinframe->fog = NULL;
6749         skinframe->reflect = NULL;
6750         skinframe->hasalpha = false;
6751
6752         skinframe->avgcolor[0] = rand() / RAND_MAX;
6753         skinframe->avgcolor[1] = rand() / RAND_MAX;
6754         skinframe->avgcolor[2] = rand() / RAND_MAX;
6755         skinframe->avgcolor[3] = 1;
6756
6757         return skinframe;
6758 }
6759
6760 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6761 typedef struct suffixinfo_s
6762 {
6763         const char *suffix;
6764         qboolean flipx, flipy, flipdiagonal;
6765 }
6766 suffixinfo_t;
6767 static suffixinfo_t suffix[3][6] =
6768 {
6769         {
6770                 {"px",   false, false, false},
6771                 {"nx",   false, false, false},
6772                 {"py",   false, false, false},
6773                 {"ny",   false, false, false},
6774                 {"pz",   false, false, false},
6775                 {"nz",   false, false, false}
6776         },
6777         {
6778                 {"posx", false, false, false},
6779                 {"negx", false, false, false},
6780                 {"posy", false, false, false},
6781                 {"negy", false, false, false},
6782                 {"posz", false, false, false},
6783                 {"negz", false, false, false}
6784         },
6785         {
6786                 {"rt",    true, false,  true},
6787                 {"lf",   false,  true,  true},
6788                 {"ft",    true,  true, false},
6789                 {"bk",   false, false, false},
6790                 {"up",    true, false,  true},
6791                 {"dn",    true, false,  true}
6792         }
6793 };
6794
6795 static int componentorder[4] = {0, 1, 2, 3};
6796
6797 rtexture_t *R_LoadCubemap(const char *basename)
6798 {
6799         int i, j, cubemapsize;
6800         unsigned char *cubemappixels, *image_buffer;
6801         rtexture_t *cubemaptexture;
6802         char name[256];
6803         // must start 0 so the first loadimagepixels has no requested width/height
6804         cubemapsize = 0;
6805         cubemappixels = NULL;
6806         cubemaptexture = NULL;
6807         // keep trying different suffix groups (posx, px, rt) until one loads
6808         for (j = 0;j < 3 && !cubemappixels;j++)
6809         {
6810                 // load the 6 images in the suffix group
6811                 for (i = 0;i < 6;i++)
6812                 {
6813                         // generate an image name based on the base and and suffix
6814                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6815                         // load it
6816                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6817                         {
6818                                 // an image loaded, make sure width and height are equal
6819                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6820                                 {
6821                                         // if this is the first image to load successfully, allocate the cubemap memory
6822                                         if (!cubemappixels && image_width >= 1)
6823                                         {
6824                                                 cubemapsize = image_width;
6825                                                 // note this clears to black, so unavailable sides are black
6826                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6827                                         }
6828                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6829                                         if (cubemappixels)
6830                                                 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);
6831                                 }
6832                                 else
6833                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6834                                 // free the image
6835                                 Mem_Free(image_buffer);
6836                         }
6837                 }
6838         }
6839         // if a cubemap loaded, upload it
6840         if (cubemappixels)
6841         {
6842                 if (developer_loading.integer)
6843                         Con_Printf("loading cubemap \"%s\"\n", basename);
6844
6845                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6846                 Mem_Free(cubemappixels);
6847         }
6848         else
6849         {
6850                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6851                 if (developer_loading.integer)
6852                 {
6853                         Con_Printf("(tried tried images ");
6854                         for (j = 0;j < 3;j++)
6855                                 for (i = 0;i < 6;i++)
6856                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6857                         Con_Print(" and was unable to find any of them).\n");
6858                 }
6859         }
6860         return cubemaptexture;
6861 }
6862
6863 rtexture_t *R_GetCubemap(const char *basename)
6864 {
6865         int i;
6866         for (i = 0;i < r_texture_numcubemaps;i++)
6867                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6868                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6869         if (i >= MAX_CUBEMAPS)
6870                 return r_texture_whitecube;
6871         r_texture_numcubemaps++;
6872         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6873         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6874         return r_texture_cubemaps[i].texture;
6875 }
6876
6877 void R_FreeCubemaps(void)
6878 {
6879         int i;
6880         for (i = 0;i < r_texture_numcubemaps;i++)
6881         {
6882                 if (developer_loading.integer)
6883                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6884                 if (r_texture_cubemaps[i].texture)
6885                         R_FreeTexture(r_texture_cubemaps[i].texture);
6886         }
6887         r_texture_numcubemaps = 0;
6888 }
6889
6890 void R_Main_FreeViewCache(void)
6891 {
6892         if (r_refdef.viewcache.entityvisible)
6893                 Mem_Free(r_refdef.viewcache.entityvisible);
6894         if (r_refdef.viewcache.world_pvsbits)
6895                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6896         if (r_refdef.viewcache.world_leafvisible)
6897                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6898         if (r_refdef.viewcache.world_surfacevisible)
6899                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6900         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6901 }
6902
6903 void R_Main_ResizeViewCache(void)
6904 {
6905         int numentities = r_refdef.scene.numentities;
6906         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6907         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6908         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6909         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6910         if (r_refdef.viewcache.maxentities < numentities)
6911         {
6912                 r_refdef.viewcache.maxentities = numentities;
6913                 if (r_refdef.viewcache.entityvisible)
6914                         Mem_Free(r_refdef.viewcache.entityvisible);
6915                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6916         }
6917         if (r_refdef.viewcache.world_numclusters != numclusters)
6918         {
6919                 r_refdef.viewcache.world_numclusters = numclusters;
6920                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6921                 if (r_refdef.viewcache.world_pvsbits)
6922                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6923                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6924         }
6925         if (r_refdef.viewcache.world_numleafs != numleafs)
6926         {
6927                 r_refdef.viewcache.world_numleafs = numleafs;
6928                 if (r_refdef.viewcache.world_leafvisible)
6929                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6930                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6931         }
6932         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6933         {
6934                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6935                 if (r_refdef.viewcache.world_surfacevisible)
6936                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6937                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6938         }
6939 }
6940
6941 extern rtexture_t *loadingscreentexture;
6942 void gl_main_start(void)
6943 {
6944         loadingscreentexture = NULL;
6945         r_texture_blanknormalmap = NULL;
6946         r_texture_white = NULL;
6947         r_texture_grey128 = NULL;
6948         r_texture_black = NULL;
6949         r_texture_whitecube = NULL;
6950         r_texture_normalizationcube = NULL;
6951         r_texture_fogattenuation = NULL;
6952         r_texture_fogheighttexture = NULL;
6953         r_texture_gammaramps = NULL;
6954         r_texture_numcubemaps = 0;
6955
6956         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6957         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6958
6959         switch(vid.renderpath)
6960         {
6961         case RENDERPATH_GL20:
6962         case RENDERPATH_CGGL:
6963         case RENDERPATH_D3D9:
6964         case RENDERPATH_D3D10:
6965         case RENDERPATH_D3D11:
6966                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6967                 Cvar_SetValueQuick(&gl_combine, 1);
6968                 Cvar_SetValueQuick(&r_glsl, 1);
6969                 r_loadnormalmap = true;
6970                 r_loadgloss = true;
6971                 r_loadfog = false;
6972                 break;
6973         case RENDERPATH_GL13:
6974                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6975                 Cvar_SetValueQuick(&gl_combine, 1);
6976                 Cvar_SetValueQuick(&r_glsl, 0);
6977                 r_loadnormalmap = false;
6978                 r_loadgloss = false;
6979                 r_loadfog = true;
6980                 break;
6981         case RENDERPATH_GL11:
6982                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6983                 Cvar_SetValueQuick(&gl_combine, 0);
6984                 Cvar_SetValueQuick(&r_glsl, 0);
6985                 r_loadnormalmap = false;
6986                 r_loadgloss = false;
6987                 r_loadfog = true;
6988                 break;
6989         }
6990
6991         R_AnimCache_Free();
6992         R_FrameData_Reset();
6993
6994         r_numqueries = 0;
6995         r_maxqueries = 0;
6996         memset(r_queries, 0, sizeof(r_queries));
6997
6998         r_qwskincache = NULL;
6999         r_qwskincache_size = 0;
7000
7001         // set up r_skinframe loading system for textures
7002         memset(&r_skinframe, 0, sizeof(r_skinframe));
7003         r_skinframe.loadsequence = 1;
7004         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7005
7006         r_main_texturepool = R_AllocTexturePool();
7007         R_BuildBlankTextures();
7008         R_BuildNoTexture();
7009         if (vid.support.arb_texture_cube_map)
7010         {
7011                 R_BuildWhiteCube();
7012                 R_BuildNormalizationCube();
7013         }
7014         r_texture_fogattenuation = NULL;
7015         r_texture_fogheighttexture = NULL;
7016         r_texture_gammaramps = NULL;
7017         //r_texture_fogintensity = NULL;
7018         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7019         memset(&r_waterstate, 0, sizeof(r_waterstate));
7020         r_glsl_permutation = NULL;
7021         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7022         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7023         glslshaderstring = NULL;
7024 #ifdef SUPPORTCG
7025         r_cg_permutation = NULL;
7026         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7027         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7028         cgshaderstring = NULL;
7029 #endif
7030 #ifdef SUPPORTD3D
7031         r_hlsl_permutation = NULL;
7032         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7033         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7034         hlslshaderstring = NULL;
7035 #endif
7036         memset(&r_svbsp, 0, sizeof (r_svbsp));
7037
7038         r_refdef.fogmasktable_density = 0;
7039 }
7040
7041 void gl_main_shutdown(void)
7042 {
7043         R_AnimCache_Free();
7044         R_FrameData_Reset();
7045
7046         R_Main_FreeViewCache();
7047
7048         switch(vid.renderpath)
7049         {
7050         case RENDERPATH_GL11:
7051         case RENDERPATH_GL13:
7052         case RENDERPATH_GL20:
7053         case RENDERPATH_CGGL:
7054                 if (r_maxqueries)
7055                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7056                 break;
7057         case RENDERPATH_D3D9:
7058                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7059                 break;
7060         case RENDERPATH_D3D10:
7061                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7062                 break;
7063         case RENDERPATH_D3D11:
7064                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7065                 break;
7066         }
7067
7068         r_numqueries = 0;
7069         r_maxqueries = 0;
7070         memset(r_queries, 0, sizeof(r_queries));
7071
7072         r_qwskincache = NULL;
7073         r_qwskincache_size = 0;
7074
7075         // clear out the r_skinframe state
7076         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7077         memset(&r_skinframe, 0, sizeof(r_skinframe));
7078
7079         if (r_svbsp.nodes)
7080                 Mem_Free(r_svbsp.nodes);
7081         memset(&r_svbsp, 0, sizeof (r_svbsp));
7082         R_FreeTexturePool(&r_main_texturepool);
7083         loadingscreentexture = NULL;
7084         r_texture_blanknormalmap = NULL;
7085         r_texture_white = NULL;
7086         r_texture_grey128 = NULL;
7087         r_texture_black = NULL;
7088         r_texture_whitecube = NULL;
7089         r_texture_normalizationcube = NULL;
7090         r_texture_fogattenuation = NULL;
7091         r_texture_fogheighttexture = NULL;
7092         r_texture_gammaramps = NULL;
7093         r_texture_numcubemaps = 0;
7094         //r_texture_fogintensity = NULL;
7095         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7096         memset(&r_waterstate, 0, sizeof(r_waterstate));
7097         R_GLSL_Restart_f();
7098 }
7099
7100 extern void CL_ParseEntityLump(char *entitystring);
7101 void gl_main_newmap(void)
7102 {
7103         // FIXME: move this code to client
7104         char *entities, entname[MAX_QPATH];
7105         if (r_qwskincache)
7106                 Mem_Free(r_qwskincache);
7107         r_qwskincache = NULL;
7108         r_qwskincache_size = 0;
7109         if (cl.worldmodel)
7110         {
7111                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7112                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7113                 {
7114                         CL_ParseEntityLump(entities);
7115                         Mem_Free(entities);
7116                         return;
7117                 }
7118                 if (cl.worldmodel->brush.entities)
7119                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7120         }
7121         R_Main_FreeViewCache();
7122
7123         R_FrameData_Reset();
7124 }
7125
7126 void GL_Main_Init(void)
7127 {
7128         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7129
7130         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7131         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7132         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7133         if (gamemode == GAME_NEHAHRA)
7134         {
7135                 Cvar_RegisterVariable (&gl_fogenable);
7136                 Cvar_RegisterVariable (&gl_fogdensity);
7137                 Cvar_RegisterVariable (&gl_fogred);
7138                 Cvar_RegisterVariable (&gl_foggreen);
7139                 Cvar_RegisterVariable (&gl_fogblue);
7140                 Cvar_RegisterVariable (&gl_fogstart);
7141                 Cvar_RegisterVariable (&gl_fogend);
7142                 Cvar_RegisterVariable (&gl_skyclip);
7143         }
7144         Cvar_RegisterVariable(&r_motionblur);
7145         Cvar_RegisterVariable(&r_motionblur_maxblur);
7146         Cvar_RegisterVariable(&r_motionblur_bmin);
7147         Cvar_RegisterVariable(&r_motionblur_vmin);
7148         Cvar_RegisterVariable(&r_motionblur_vmax);
7149         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7150         Cvar_RegisterVariable(&r_motionblur_randomize);
7151         Cvar_RegisterVariable(&r_damageblur);
7152         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7153         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7154         Cvar_RegisterVariable(&r_equalize_entities_by);
7155         Cvar_RegisterVariable(&r_equalize_entities_to);
7156         Cvar_RegisterVariable(&r_depthfirst);
7157         Cvar_RegisterVariable(&r_useinfinitefarclip);
7158         Cvar_RegisterVariable(&r_farclip_base);
7159         Cvar_RegisterVariable(&r_farclip_world);
7160         Cvar_RegisterVariable(&r_nearclip);
7161         Cvar_RegisterVariable(&r_showbboxes);
7162         Cvar_RegisterVariable(&r_showsurfaces);
7163         Cvar_RegisterVariable(&r_showtris);
7164         Cvar_RegisterVariable(&r_shownormals);
7165         Cvar_RegisterVariable(&r_showlighting);
7166         Cvar_RegisterVariable(&r_showshadowvolumes);
7167         Cvar_RegisterVariable(&r_showcollisionbrushes);
7168         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7169         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7170         Cvar_RegisterVariable(&r_showdisabledepthtest);
7171         Cvar_RegisterVariable(&r_drawportals);
7172         Cvar_RegisterVariable(&r_drawentities);
7173         Cvar_RegisterVariable(&r_draw2d);
7174         Cvar_RegisterVariable(&r_drawworld);
7175         Cvar_RegisterVariable(&r_cullentities_trace);
7176         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7177         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7178         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7179         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7180         Cvar_RegisterVariable(&r_drawviewmodel);
7181         Cvar_RegisterVariable(&r_drawexteriormodel);
7182         Cvar_RegisterVariable(&r_speeds);
7183         Cvar_RegisterVariable(&r_fullbrights);
7184         Cvar_RegisterVariable(&r_wateralpha);
7185         Cvar_RegisterVariable(&r_dynamic);
7186         Cvar_RegisterVariable(&r_fullbright);
7187         Cvar_RegisterVariable(&r_shadows);
7188         Cvar_RegisterVariable(&r_shadows_darken);
7189         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7190         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7191         Cvar_RegisterVariable(&r_shadows_throwdistance);
7192         Cvar_RegisterVariable(&r_shadows_throwdirection);
7193         Cvar_RegisterVariable(&r_shadows_focus);
7194         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7195         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7196         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7197         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7198         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7199         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7200         Cvar_RegisterVariable(&r_fog_exp2);
7201         Cvar_RegisterVariable(&r_drawfog);
7202         Cvar_RegisterVariable(&r_transparentdepthmasking);
7203         Cvar_RegisterVariable(&r_texture_dds_load);
7204         Cvar_RegisterVariable(&r_texture_dds_save);
7205         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7206         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7207         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7208         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7209         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7210         Cvar_RegisterVariable(&r_textureunits);
7211         Cvar_RegisterVariable(&gl_combine);
7212         Cvar_RegisterVariable(&r_glsl);
7213         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7214         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7215         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7216         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7217         Cvar_RegisterVariable(&r_glsl_postprocess);
7218         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7219         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7220         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7221         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7222         Cvar_RegisterVariable(&r_water);
7223         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7224         Cvar_RegisterVariable(&r_water_clippingplanebias);
7225         Cvar_RegisterVariable(&r_water_refractdistort);
7226         Cvar_RegisterVariable(&r_water_reflectdistort);
7227         Cvar_RegisterVariable(&r_lerpsprites);
7228         Cvar_RegisterVariable(&r_lerpmodels);
7229         Cvar_RegisterVariable(&r_lerplightstyles);
7230         Cvar_RegisterVariable(&r_waterscroll);
7231         Cvar_RegisterVariable(&r_bloom);
7232         Cvar_RegisterVariable(&r_bloom_colorscale);
7233         Cvar_RegisterVariable(&r_bloom_brighten);
7234         Cvar_RegisterVariable(&r_bloom_blur);
7235         Cvar_RegisterVariable(&r_bloom_resolution);
7236         Cvar_RegisterVariable(&r_bloom_colorexponent);
7237         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7238         Cvar_RegisterVariable(&r_hdr);
7239         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7240         Cvar_RegisterVariable(&r_hdr_glowintensity);
7241         Cvar_RegisterVariable(&r_hdr_range);
7242         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7243         Cvar_RegisterVariable(&developer_texturelogging);
7244         Cvar_RegisterVariable(&gl_lightmaps);
7245         Cvar_RegisterVariable(&r_test);
7246         Cvar_RegisterVariable(&r_glsl_saturation);
7247         Cvar_RegisterVariable(&r_framedatasize);
7248         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7249                 Cvar_SetValue("r_fullbrights", 0);
7250         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7251
7252         Cvar_RegisterVariable(&r_track_sprites);
7253         Cvar_RegisterVariable(&r_track_sprites_flags);
7254         Cvar_RegisterVariable(&r_track_sprites_scalew);
7255         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7256         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7257         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7258 }
7259
7260 extern void R_Textures_Init(void);
7261 extern void GL_Draw_Init(void);
7262 extern void GL_Main_Init(void);
7263 extern void R_Shadow_Init(void);
7264 extern void R_Sky_Init(void);
7265 extern void GL_Surf_Init(void);
7266 extern void R_Particles_Init(void);
7267 extern void R_Explosion_Init(void);
7268 extern void gl_backend_init(void);
7269 extern void Sbar_Init(void);
7270 extern void R_LightningBeams_Init(void);
7271 extern void Mod_RenderInit(void);
7272 extern void Font_Init(void);
7273
7274 void Render_Init(void)
7275 {
7276         gl_backend_init();
7277         R_Textures_Init();
7278         GL_Main_Init();
7279         Font_Init();
7280         GL_Draw_Init();
7281         R_Shadow_Init();
7282         R_Sky_Init();
7283         GL_Surf_Init();
7284         Sbar_Init();
7285         R_Particles_Init();
7286         R_Explosion_Init();
7287         R_LightningBeams_Init();
7288         Mod_RenderInit();
7289 }
7290
7291 /*
7292 ===============
7293 GL_Init
7294 ===============
7295 */
7296 extern char *ENGINE_EXTENSIONS;
7297 void GL_Init (void)
7298 {
7299         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7300         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7301         gl_version = (const char *)qglGetString(GL_VERSION);
7302         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7303
7304         if (!gl_extensions)
7305                 gl_extensions = "";
7306         if (!gl_platformextensions)
7307                 gl_platformextensions = "";
7308
7309         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7310         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7311         Con_Printf("GL_VERSION: %s\n", gl_version);
7312         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7313         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7314
7315         VID_CheckExtensions();
7316
7317         // LordHavoc: report supported extensions
7318         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7319
7320         // clear to black (loading plaque will be seen over this)
7321         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7322 }
7323
7324 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7325 {
7326         int i;
7327         mplane_t *p;
7328         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7329         {
7330                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7331                 if (i == 4)
7332                         continue;
7333                 p = r_refdef.view.frustum + i;
7334                 switch(p->signbits)
7335                 {
7336                 default:
7337                 case 0:
7338                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7339                                 return true;
7340                         break;
7341                 case 1:
7342                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7343                                 return true;
7344                         break;
7345                 case 2:
7346                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7347                                 return true;
7348                         break;
7349                 case 3:
7350                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7351                                 return true;
7352                         break;
7353                 case 4:
7354                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7355                                 return true;
7356                         break;
7357                 case 5:
7358                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7359                                 return true;
7360                         break;
7361                 case 6:
7362                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7363                                 return true;
7364                         break;
7365                 case 7:
7366                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7367                                 return true;
7368                         break;
7369                 }
7370         }
7371         return false;
7372 }
7373
7374 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7375 {
7376         int i;
7377         const mplane_t *p;
7378         for (i = 0;i < numplanes;i++)
7379         {
7380                 p = planes + i;
7381                 switch(p->signbits)
7382                 {
7383                 default:
7384                 case 0:
7385                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7386                                 return true;
7387                         break;
7388                 case 1:
7389                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7390                                 return true;
7391                         break;
7392                 case 2:
7393                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7394                                 return true;
7395                         break;
7396                 case 3:
7397                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7398                                 return true;
7399                         break;
7400                 case 4:
7401                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7402                                 return true;
7403                         break;
7404                 case 5:
7405                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7406                                 return true;
7407                         break;
7408                 case 6:
7409                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7410                                 return true;
7411                         break;
7412                 case 7:
7413                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7414                                 return true;
7415                         break;
7416                 }
7417         }
7418         return false;
7419 }
7420
7421 //==================================================================================
7422
7423 // LordHavoc: this stores temporary data used within the same frame
7424
7425 qboolean r_framedata_failed;
7426 static size_t r_framedata_size;
7427 static size_t r_framedata_current;
7428 static void *r_framedata_base;
7429
7430 void R_FrameData_Reset(void)
7431 {
7432         if (r_framedata_base)
7433                 Mem_Free(r_framedata_base);
7434         r_framedata_base = NULL;
7435         r_framedata_size = 0;
7436         r_framedata_current = 0;
7437         r_framedata_failed = false;
7438 }
7439
7440 void R_FrameData_NewFrame(void)
7441 {
7442         size_t wantedsize;
7443         if (r_framedata_failed)
7444                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7445         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7446         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7447         if (r_framedata_size != wantedsize)
7448         {
7449                 r_framedata_size = wantedsize;
7450                 if (r_framedata_base)
7451                         Mem_Free(r_framedata_base);
7452                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7453         }
7454         r_framedata_current = 0;
7455         r_framedata_failed = false;
7456 }
7457
7458 void *R_FrameData_Alloc(size_t size)
7459 {
7460         void *data;
7461
7462         // align to 16 byte boundary
7463         size = (size + 15) & ~15;
7464         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7465         r_framedata_current += size;
7466
7467         // check overflow
7468         if (r_framedata_current > r_framedata_size)
7469                 r_framedata_failed = true;
7470
7471         // return NULL on everything after a failure
7472         if (r_framedata_failed)
7473                 return NULL;
7474
7475         return data;
7476 }
7477
7478 void *R_FrameData_Store(size_t size, void *data)
7479 {
7480         void *d = R_FrameData_Alloc(size);
7481         if (d)
7482                 memcpy(d, data, size);
7483         return d;
7484 }
7485
7486 //==================================================================================
7487
7488 // LordHavoc: animcache originally written by Echon, rewritten since then
7489
7490 /**
7491  * Animation cache prevents re-generating mesh data for an animated model
7492  * multiple times in one frame for lighting, shadowing, reflections, etc.
7493  */
7494
7495 void R_AnimCache_Free(void)
7496 {
7497 }
7498
7499 void R_AnimCache_ClearCache(void)
7500 {
7501         int i;
7502         entity_render_t *ent;
7503
7504         for (i = 0;i < r_refdef.scene.numentities;i++)
7505         {
7506                 ent = r_refdef.scene.entities[i];
7507                 ent->animcache_vertex3f = NULL;
7508                 ent->animcache_normal3f = NULL;
7509                 ent->animcache_svector3f = NULL;
7510                 ent->animcache_tvector3f = NULL;
7511                 ent->animcache_vertexposition = NULL;
7512                 ent->animcache_vertexmesh = NULL;
7513                 ent->animcache_vertexpositionbuffer = NULL;
7514                 ent->animcache_vertexmeshbuffer = NULL;
7515         }
7516 }
7517
7518 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7519 {
7520         int i;
7521
7522         // identical memory layout, so no need to allocate...
7523         // this also provides the vertexposition structure to everything, e.g.
7524         // depth masked rendering currently uses it even if having separate
7525         // arrays
7526         // NOTE: get rid of this optimization if changing it to e.g. 4f
7527         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7528
7529         // TODO:
7530         // get rid of following uses of VERTEXPOSITION, change to the array:
7531         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7532         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7533         // R_DrawTextureSurfaceList_DepthOnly
7534         // R_Q1BSP_DrawShadowMap
7535
7536         switch(vid.renderpath)
7537         {
7538         case RENDERPATH_GL20:
7539         case RENDERPATH_CGGL:
7540                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7541                 if (gl_mesh_separatearrays.integer)
7542                         return;
7543                 break;
7544         case RENDERPATH_D3D9:
7545         case RENDERPATH_D3D10:
7546         case RENDERPATH_D3D11:
7547                 // always need the meshbuffers
7548                 break;
7549         case RENDERPATH_GL13:
7550         case RENDERPATH_GL11:
7551                 // never need the meshbuffers
7552                 return;
7553         }
7554
7555         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7556                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7557         /*
7558         if (!ent->animcache_vertexposition)
7559                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7560         */
7561         if (ent->animcache_vertexposition)
7562         {
7563                 /*
7564                 for (i = 0;i < numvertices;i++)
7565                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7566                 */
7567                 // TODO: upload vertex buffer?
7568         }
7569         if (ent->animcache_vertexmesh)
7570         {
7571                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7572                 for (i = 0;i < numvertices;i++)
7573                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7574                 if (ent->animcache_svector3f)
7575                         for (i = 0;i < numvertices;i++)
7576                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7577                 if (ent->animcache_tvector3f)
7578                         for (i = 0;i < numvertices;i++)
7579                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7580                 if (ent->animcache_normal3f)
7581                         for (i = 0;i < numvertices;i++)
7582                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7583                 // TODO: upload vertex buffer?
7584         }
7585 }
7586
7587 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7588 {
7589         dp_model_t *model = ent->model;
7590         int numvertices;
7591         // see if it's already cached this frame
7592         if (ent->animcache_vertex3f)
7593         {
7594                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7595                 if (wantnormals || wanttangents)
7596                 {
7597                         if (ent->animcache_normal3f)
7598                                 wantnormals = false;
7599                         if (ent->animcache_svector3f)
7600                                 wanttangents = false;
7601                         if (wantnormals || wanttangents)
7602                         {
7603                                 numvertices = model->surfmesh.num_vertices;
7604                                 if (wantnormals)
7605                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7606                                 if (wanttangents)
7607                                 {
7608                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7609                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7610                                 }
7611                                 if (!r_framedata_failed)
7612                                 {
7613                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7614                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7615                                 }
7616                         }
7617                 }
7618         }
7619         else
7620         {
7621                 // see if this ent is worth caching
7622                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7623                         return false;
7624                 // get some memory for this entity and generate mesh data
7625                 numvertices = model->surfmesh.num_vertices;
7626                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7627                 if (wantnormals)
7628                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7629                 if (wanttangents)
7630                 {
7631                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7632                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7633                 }
7634                 if (!r_framedata_failed)
7635                 {
7636                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7637                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7638                 }
7639         }
7640         return !r_framedata_failed;
7641 }
7642
7643 void R_AnimCache_CacheVisibleEntities(void)
7644 {
7645         int i;
7646         qboolean wantnormals = true;
7647         qboolean wanttangents = !r_showsurfaces.integer;
7648
7649         switch(vid.renderpath)
7650         {
7651         case RENDERPATH_GL20:
7652         case RENDERPATH_CGGL:
7653         case RENDERPATH_D3D9:
7654         case RENDERPATH_D3D10:
7655         case RENDERPATH_D3D11:
7656                 break;
7657         case RENDERPATH_GL13:
7658         case RENDERPATH_GL11:
7659                 wanttangents = false;
7660                 break;
7661         }
7662
7663         if (r_shownormals.integer)
7664                 wanttangents = wantnormals = true;
7665
7666         // TODO: thread this
7667         // NOTE: R_PrepareRTLights() also caches entities
7668
7669         for (i = 0;i < r_refdef.scene.numentities;i++)
7670                 if (r_refdef.viewcache.entityvisible[i])
7671                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7672 }
7673
7674 //==================================================================================
7675
7676 static void R_View_UpdateEntityLighting (void)
7677 {
7678         int i;
7679         entity_render_t *ent;
7680         vec3_t tempdiffusenormal, avg;
7681         vec_t f, fa, fd, fdd;
7682         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7683
7684         for (i = 0;i < r_refdef.scene.numentities;i++)
7685         {
7686                 ent = r_refdef.scene.entities[i];
7687
7688                 // skip unseen models
7689                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7690                         continue;
7691
7692                 // skip bsp models
7693                 if (ent->model && ent->model->brush.num_leafs)
7694                 {
7695                         // TODO: use modellight for r_ambient settings on world?
7696                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7697                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7698                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7699                         continue;
7700                 }
7701
7702                 // fetch the lighting from the worldmodel data
7703                 VectorClear(ent->modellight_ambient);
7704                 VectorClear(ent->modellight_diffuse);
7705                 VectorClear(tempdiffusenormal);
7706                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7707                 {
7708                         vec3_t org;
7709                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7710                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7711                         if(ent->flags & RENDER_EQUALIZE)
7712                         {
7713                                 // first fix up ambient lighting...
7714                                 if(r_equalize_entities_minambient.value > 0)
7715                                 {
7716                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7717                                         if(fd > 0)
7718                                         {
7719                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7720                                                 if(fa < r_equalize_entities_minambient.value * fd)
7721                                                 {
7722                                                         // solve:
7723                                                         //   fa'/fd' = minambient
7724                                                         //   fa'+0.25*fd' = fa+0.25*fd
7725                                                         //   ...
7726                                                         //   fa' = fd' * minambient
7727                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7728                                                         //   ...
7729                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7730                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7731                                                         //   ...
7732                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7733                                                         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
7734                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7735                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7736                                                 }
7737                                         }
7738                                 }
7739
7740                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7741                                 {
7742                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7743                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7744                                         if(f > 0)
7745                                         {
7746                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7747                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7748                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7749                                         }
7750                                 }
7751                         }
7752                 }
7753                 else // highly rare
7754                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7755
7756                 // move the light direction into modelspace coordinates for lighting code
7757                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7758                 if(VectorLength2(ent->modellight_lightdir) == 0)
7759                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7760                 VectorNormalize(ent->modellight_lightdir);
7761         }
7762 }
7763
7764 #define MAX_LINEOFSIGHTTRACES 64
7765
7766 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7767 {
7768         int i;
7769         vec3_t boxmins, boxmaxs;
7770         vec3_t start;
7771         vec3_t end;
7772         dp_model_t *model = r_refdef.scene.worldmodel;
7773
7774         if (!model || !model->brush.TraceLineOfSight)
7775                 return true;
7776
7777         // expand the box a little
7778         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7779         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7780         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7781         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7782         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7783         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7784
7785         // return true if eye is inside enlarged box
7786         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7787                 return true;
7788
7789         // try center
7790         VectorCopy(eye, start);
7791         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7792         if (model->brush.TraceLineOfSight(model, start, end))
7793                 return true;
7794
7795         // try various random positions
7796         for (i = 0;i < numsamples;i++)
7797         {
7798                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7799                 if (model->brush.TraceLineOfSight(model, start, end))
7800                         return true;
7801         }
7802
7803         return false;
7804 }
7805
7806
7807 static void R_View_UpdateEntityVisible (void)
7808 {
7809         int i;
7810         int renderimask;
7811         int samples;
7812         entity_render_t *ent;
7813
7814         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7815                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7816                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7817                 :                                                          RENDER_EXTERIORMODEL;
7818         if (!r_drawviewmodel.integer)
7819                 renderimask |= RENDER_VIEWMODEL;
7820         if (!r_drawexteriormodel.integer)
7821                 renderimask |= RENDER_EXTERIORMODEL;
7822         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7823         {
7824                 // worldmodel can check visibility
7825                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7826                 for (i = 0;i < r_refdef.scene.numentities;i++)
7827                 {
7828                         ent = r_refdef.scene.entities[i];
7829                         if (!(ent->flags & renderimask))
7830                         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)))
7831                         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))
7832                                 r_refdef.viewcache.entityvisible[i] = true;
7833                 }
7834                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7835                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7836                 {
7837                         for (i = 0;i < r_refdef.scene.numentities;i++)
7838                         {
7839                                 ent = r_refdef.scene.entities[i];
7840                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7841                                 {
7842                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7843                                         if (samples < 0)
7844                                                 continue; // temp entities do pvs only
7845                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7846                                                 ent->last_trace_visibility = realtime;
7847                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7848                                                 r_refdef.viewcache.entityvisible[i] = 0;
7849                                 }
7850                         }
7851                 }
7852         }
7853         else
7854         {
7855                 // no worldmodel or it can't check visibility
7856                 for (i = 0;i < r_refdef.scene.numentities;i++)
7857                 {
7858                         ent = r_refdef.scene.entities[i];
7859                         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));
7860                 }
7861         }
7862 }
7863
7864 /// only used if skyrendermasked, and normally returns false
7865 int R_DrawBrushModelsSky (void)
7866 {
7867         int i, sky;
7868         entity_render_t *ent;
7869
7870         sky = false;
7871         for (i = 0;i < r_refdef.scene.numentities;i++)
7872         {
7873                 if (!r_refdef.viewcache.entityvisible[i])
7874                         continue;
7875                 ent = r_refdef.scene.entities[i];
7876                 if (!ent->model || !ent->model->DrawSky)
7877                         continue;
7878                 ent->model->DrawSky(ent);
7879                 sky = true;
7880         }
7881         return sky;
7882 }
7883
7884 static void R_DrawNoModel(entity_render_t *ent);
7885 static void R_DrawModels(void)
7886 {
7887         int i;
7888         entity_render_t *ent;
7889
7890         for (i = 0;i < r_refdef.scene.numentities;i++)
7891         {
7892                 if (!r_refdef.viewcache.entityvisible[i])
7893                         continue;
7894                 ent = r_refdef.scene.entities[i];
7895                 r_refdef.stats.entities++;
7896                 if (ent->model && ent->model->Draw != NULL)
7897                         ent->model->Draw(ent);
7898                 else
7899                         R_DrawNoModel(ent);
7900         }
7901 }
7902
7903 static void R_DrawModelsDepth(void)
7904 {
7905         int i;
7906         entity_render_t *ent;
7907
7908         for (i = 0;i < r_refdef.scene.numentities;i++)
7909         {
7910                 if (!r_refdef.viewcache.entityvisible[i])
7911                         continue;
7912                 ent = r_refdef.scene.entities[i];
7913                 if (ent->model && ent->model->DrawDepth != NULL)
7914                         ent->model->DrawDepth(ent);
7915         }
7916 }
7917
7918 static void R_DrawModelsDebug(void)
7919 {
7920         int i;
7921         entity_render_t *ent;
7922
7923         for (i = 0;i < r_refdef.scene.numentities;i++)
7924         {
7925                 if (!r_refdef.viewcache.entityvisible[i])
7926                         continue;
7927                 ent = r_refdef.scene.entities[i];
7928                 if (ent->model && ent->model->DrawDebug != NULL)
7929                         ent->model->DrawDebug(ent);
7930         }
7931 }
7932
7933 static void R_DrawModelsAddWaterPlanes(void)
7934 {
7935         int i;
7936         entity_render_t *ent;
7937
7938         for (i = 0;i < r_refdef.scene.numentities;i++)
7939         {
7940                 if (!r_refdef.viewcache.entityvisible[i])
7941                         continue;
7942                 ent = r_refdef.scene.entities[i];
7943                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7944                         ent->model->DrawAddWaterPlanes(ent);
7945         }
7946 }
7947
7948 static void R_View_SetFrustum(void)
7949 {
7950         int i;
7951         double slopex, slopey;
7952         vec3_t forward, left, up, origin;
7953
7954         // we can't trust r_refdef.view.forward and friends in reflected scenes
7955         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7956
7957 #if 0
7958         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7959         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7960         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7961         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7962         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7963         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7964         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7965         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7966         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7967         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7968         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7969         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7970 #endif
7971
7972 #if 0
7973         zNear = r_refdef.nearclip;
7974         nudge = 1.0 - 1.0 / (1<<23);
7975         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7976         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7977         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7978         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7979         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7980         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7981         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7982         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7983 #endif
7984
7985
7986
7987 #if 0
7988         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7989         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7990         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7991         r_refdef.view.frustum[0].dist = m[15] - m[12];
7992
7993         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7994         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7995         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7996         r_refdef.view.frustum[1].dist = m[15] + m[12];
7997
7998         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7999         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8000         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8001         r_refdef.view.frustum[2].dist = m[15] - m[13];
8002
8003         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8004         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8005         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8006         r_refdef.view.frustum[3].dist = m[15] + m[13];
8007
8008         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8009         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8010         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8011         r_refdef.view.frustum[4].dist = m[15] - m[14];
8012
8013         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8014         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8015         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8016         r_refdef.view.frustum[5].dist = m[15] + m[14];
8017 #endif
8018
8019         if (r_refdef.view.useperspective)
8020         {
8021                 slopex = 1.0 / r_refdef.view.frustum_x;
8022                 slopey = 1.0 / r_refdef.view.frustum_y;
8023                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8024                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8025                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8026                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8027                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8028
8029                 // Leaving those out was a mistake, those were in the old code, and they
8030                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8031                 // I couldn't reproduce it after adding those normalizations. --blub
8032                 VectorNormalize(r_refdef.view.frustum[0].normal);
8033                 VectorNormalize(r_refdef.view.frustum[1].normal);
8034                 VectorNormalize(r_refdef.view.frustum[2].normal);
8035                 VectorNormalize(r_refdef.view.frustum[3].normal);
8036
8037                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8038                 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]);
8039                 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]);
8040                 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]);
8041                 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]);
8042
8043                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8044                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8045                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8046                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8047                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8048         }
8049         else
8050         {
8051                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8052                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8053                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8054                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8055                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8056                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8057                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8058                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8059                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8060                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8061         }
8062         r_refdef.view.numfrustumplanes = 5;
8063
8064         if (r_refdef.view.useclipplane)
8065         {
8066                 r_refdef.view.numfrustumplanes = 6;
8067                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8068         }
8069
8070         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8071                 PlaneClassify(r_refdef.view.frustum + i);
8072
8073         // LordHavoc: note to all quake engine coders, Quake had a special case
8074         // for 90 degrees which assumed a square view (wrong), so I removed it,
8075         // Quake2 has it disabled as well.
8076
8077         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8078         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8079         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8080         //PlaneClassify(&frustum[0]);
8081
8082         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8083         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8084         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8085         //PlaneClassify(&frustum[1]);
8086
8087         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8088         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8089         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8090         //PlaneClassify(&frustum[2]);
8091
8092         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8093         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8094         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8095         //PlaneClassify(&frustum[3]);
8096
8097         // nearclip plane
8098         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8099         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8100         //PlaneClassify(&frustum[4]);
8101 }
8102
8103 void R_View_Update(void)
8104 {
8105         R_Main_ResizeViewCache();
8106         R_View_SetFrustum();
8107         R_View_WorldVisibility(r_refdef.view.useclipplane);
8108         R_View_UpdateEntityVisible();
8109         R_View_UpdateEntityLighting();
8110 }
8111
8112 void R_SetupView(qboolean allowwaterclippingplane)
8113 {
8114         const float *customclipplane = NULL;
8115         float plane[4];
8116         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8117         {
8118                 // LordHavoc: couldn't figure out how to make this approach the
8119                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8120                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8121                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8122                         dist = r_refdef.view.clipplane.dist;
8123                 plane[0] = r_refdef.view.clipplane.normal[0];
8124                 plane[1] = r_refdef.view.clipplane.normal[1];
8125                 plane[2] = r_refdef.view.clipplane.normal[2];
8126                 plane[3] = dist;
8127                 customclipplane = plane;
8128         }
8129
8130         if (!r_refdef.view.useperspective)
8131                 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);
8132         else if (vid.stencil && r_useinfinitefarclip.integer)
8133                 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);
8134         else
8135                 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);
8136         R_SetViewport(&r_refdef.view.viewport);
8137 }
8138
8139 void R_EntityMatrix(const matrix4x4_t *matrix)
8140 {
8141         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8142         {
8143                 gl_modelmatrixchanged = false;
8144                 gl_modelmatrix = *matrix;
8145                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8146                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8147                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8148                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8149                 CHECKGLERROR
8150                 switch(vid.renderpath)
8151                 {
8152                 case RENDERPATH_D3D9:
8153 #ifdef SUPPORTD3D
8154                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8155                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8156 #endif
8157                         break;
8158                 case RENDERPATH_D3D10:
8159                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8160                         break;
8161                 case RENDERPATH_D3D11:
8162                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8163                         break;
8164                 case RENDERPATH_GL20:
8165                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8166                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8167                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8168                         break;
8169                 case RENDERPATH_CGGL:
8170 #ifdef SUPPORTCG
8171                         CHECKCGERROR
8172                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8173                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8174                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8175 #endif
8176                         break;
8177                 case RENDERPATH_GL13:
8178                 case RENDERPATH_GL11:
8179                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8180                         break;
8181                 }
8182         }
8183 }
8184
8185 void R_ResetViewRendering2D(void)
8186 {
8187         r_viewport_t viewport;
8188         DrawQ_Finish();
8189
8190         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8191         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);
8192         R_SetViewport(&viewport);
8193         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8194         GL_Color(1, 1, 1, 1);
8195         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8196         GL_BlendFunc(GL_ONE, GL_ZERO);
8197         GL_AlphaTest(false);
8198         GL_ScissorTest(false);
8199         GL_DepthMask(false);
8200         GL_DepthRange(0, 1);
8201         GL_DepthTest(false);
8202         GL_DepthFunc(GL_LEQUAL);
8203         R_EntityMatrix(&identitymatrix);
8204         R_Mesh_ResetTextureState();
8205         GL_PolygonOffset(0, 0);
8206         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8207         switch(vid.renderpath)
8208         {
8209         case RENDERPATH_GL11:
8210         case RENDERPATH_GL13:
8211         case RENDERPATH_GL20:
8212         case RENDERPATH_CGGL:
8213                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8214                 break;
8215         case RENDERPATH_D3D9:
8216         case RENDERPATH_D3D10:
8217         case RENDERPATH_D3D11:
8218                 break;
8219         }
8220         GL_CullFace(GL_NONE);
8221 }
8222
8223 void R_ResetViewRendering3D(void)
8224 {
8225         DrawQ_Finish();
8226
8227         R_SetupView(true);
8228         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8229         GL_Color(1, 1, 1, 1);
8230         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8231         GL_BlendFunc(GL_ONE, GL_ZERO);
8232         GL_AlphaTest(false);
8233         GL_ScissorTest(true);
8234         GL_DepthMask(true);
8235         GL_DepthRange(0, 1);
8236         GL_DepthTest(true);
8237         GL_DepthFunc(GL_LEQUAL);
8238         R_EntityMatrix(&identitymatrix);
8239         R_Mesh_ResetTextureState();
8240         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8241         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8242         switch(vid.renderpath)
8243         {
8244         case RENDERPATH_GL11:
8245         case RENDERPATH_GL13:
8246         case RENDERPATH_GL20:
8247         case RENDERPATH_CGGL:
8248                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8249                 break;
8250         case RENDERPATH_D3D9:
8251         case RENDERPATH_D3D10:
8252         case RENDERPATH_D3D11:
8253                 break;
8254         }
8255         GL_CullFace(r_refdef.view.cullface_back);
8256 }
8257
8258 /*
8259 ================
8260 R_RenderView_UpdateViewVectors
8261 ================
8262 */
8263 static void R_RenderView_UpdateViewVectors(void)
8264 {
8265         // break apart the view matrix into vectors for various purposes
8266         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8267         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8268         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8269         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8270         // make an inverted copy of the view matrix for tracking sprites
8271         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8272 }
8273
8274 void R_RenderScene(void);
8275 void R_RenderWaterPlanes(void);
8276
8277 static void R_Water_StartFrame(void)
8278 {
8279         int i;
8280         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8281         r_waterstate_waterplane_t *p;
8282
8283         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8284                 return;
8285
8286         switch(vid.renderpath)
8287         {
8288         case RENDERPATH_GL20:
8289         case RENDERPATH_CGGL:
8290         case RENDERPATH_D3D9:
8291         case RENDERPATH_D3D10:
8292         case RENDERPATH_D3D11:
8293                 break;
8294         case RENDERPATH_GL13:
8295         case RENDERPATH_GL11:
8296                 return;
8297         }
8298
8299         // set waterwidth and waterheight to the water resolution that will be
8300         // used (often less than the screen resolution for faster rendering)
8301         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8302         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8303
8304         // calculate desired texture sizes
8305         // can't use water if the card does not support the texture size
8306         if (!r_water.integer || r_showsurfaces.integer)
8307                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8308         else if (vid.support.arb_texture_non_power_of_two)
8309         {
8310                 texturewidth = waterwidth;
8311                 textureheight = waterheight;
8312                 camerawidth = waterwidth;
8313                 cameraheight = waterheight;
8314         }
8315         else
8316         {
8317                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8318                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8319                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8320                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8321         }
8322
8323         // allocate textures as needed
8324         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8325         {
8326                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8327                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8328                 {
8329                         if (p->texture_refraction)
8330                                 R_FreeTexture(p->texture_refraction);
8331                         p->texture_refraction = NULL;
8332                         if (p->texture_reflection)
8333                                 R_FreeTexture(p->texture_reflection);
8334                         p->texture_reflection = NULL;
8335                         if (p->texture_camera)
8336                                 R_FreeTexture(p->texture_camera);
8337                         p->texture_camera = NULL;
8338                 }
8339                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8340                 r_waterstate.texturewidth = texturewidth;
8341                 r_waterstate.textureheight = textureheight;
8342                 r_waterstate.camerawidth = camerawidth;
8343                 r_waterstate.cameraheight = cameraheight;
8344         }
8345
8346         if (r_waterstate.texturewidth)
8347         {
8348                 r_waterstate.enabled = true;
8349
8350                 // when doing a reduced render (HDR) we want to use a smaller area
8351                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8352                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8353
8354                 // set up variables that will be used in shader setup
8355                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8356                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8357                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8358                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8359         }
8360
8361         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8362         r_waterstate.numwaterplanes = 0;
8363 }
8364
8365 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8366 {
8367         int triangleindex, planeindex;
8368         const int *e;
8369         vec3_t vert[3];
8370         vec3_t normal;
8371         vec3_t center;
8372         mplane_t plane;
8373         int cam_ent;
8374         r_waterstate_waterplane_t *p;
8375         texture_t *t = R_GetCurrentTexture(surface->texture);
8376         cam_ent = t->camera_entity;
8377         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8378                 cam_ent = 0;
8379
8380         // just use the first triangle with a valid normal for any decisions
8381         VectorClear(normal);
8382         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8383         {
8384                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8385                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8386                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8387                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8388                 if (VectorLength2(normal) >= 0.001)
8389                         break;
8390         }
8391
8392         VectorCopy(normal, plane.normal);
8393         VectorNormalize(plane.normal);
8394         plane.dist = DotProduct(vert[0], plane.normal);
8395         PlaneClassify(&plane);
8396         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8397         {
8398                 // skip backfaces (except if nocullface is set)
8399                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8400                         return;
8401                 VectorNegate(plane.normal, plane.normal);
8402                 plane.dist *= -1;
8403                 PlaneClassify(&plane);
8404         }
8405
8406
8407         // find a matching plane if there is one
8408         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8409                 if(p->camera_entity == t->camera_entity)
8410                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8411                                 break;
8412         if (planeindex >= r_waterstate.maxwaterplanes)
8413                 return; // nothing we can do, out of planes
8414
8415         // if this triangle does not fit any known plane rendered this frame, add one
8416         if (planeindex >= r_waterstate.numwaterplanes)
8417         {
8418                 // store the new plane
8419                 r_waterstate.numwaterplanes++;
8420                 p->plane = plane;
8421                 // clear materialflags and pvs
8422                 p->materialflags = 0;
8423                 p->pvsvalid = false;
8424                 p->camera_entity = t->camera_entity;
8425         }
8426         // merge this surface's materialflags into the waterplane
8427         p->materialflags |= t->currentmaterialflags;
8428         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8429         {
8430                 // merge this surface's PVS into the waterplane
8431                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8432                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8433                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8434                 {
8435                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8436                         p->pvsvalid = true;
8437                 }
8438         }
8439 }
8440
8441 static void R_Water_ProcessPlanes(void)
8442 {
8443         r_refdef_view_t originalview;
8444         r_refdef_view_t myview;
8445         int planeindex;
8446         r_waterstate_waterplane_t *p;
8447         vec3_t visorigin;
8448
8449         originalview = r_refdef.view;
8450
8451         // make sure enough textures are allocated
8452         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8453         {
8454                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8455                 {
8456                         if (!p->texture_refraction)
8457                                 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);
8458                         if (!p->texture_refraction)
8459                                 goto error;
8460                 }
8461                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8462                 {
8463                         if (!p->texture_camera)
8464                                 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);
8465                         if (!p->texture_camera)
8466                                 goto error;
8467                 }
8468
8469                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8470                 {
8471                         if (!p->texture_reflection)
8472                                 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);
8473                         if (!p->texture_reflection)
8474                                 goto error;
8475                 }
8476         }
8477
8478         // render views
8479         r_refdef.view = originalview;
8480         r_refdef.view.showdebug = false;
8481         r_refdef.view.width = r_waterstate.waterwidth;
8482         r_refdef.view.height = r_waterstate.waterheight;
8483         r_refdef.view.useclipplane = true;
8484         myview = r_refdef.view;
8485         r_waterstate.renderingscene = true;
8486         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8487         {
8488                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8489                 {
8490                         r_refdef.view = myview;
8491                         // render reflected scene and copy into texture
8492                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8493                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8494                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8495                         r_refdef.view.clipplane = p->plane;
8496                         // reverse the cullface settings for this render
8497                         r_refdef.view.cullface_front = GL_FRONT;
8498                         r_refdef.view.cullface_back = GL_BACK;
8499                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8500                         {
8501                                 r_refdef.view.usecustompvs = true;
8502                                 if (p->pvsvalid)
8503                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8504                                 else
8505                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8506                         }
8507
8508                         R_ResetViewRendering3D();
8509                         R_ClearScreen(r_refdef.fogenabled);
8510                         R_View_Update();
8511                         R_RenderScene();
8512
8513                         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);
8514                 }
8515
8516                 // render the normal view scene and copy into texture
8517                 // (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)
8518                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8519                 {
8520                         r_waterstate.renderingrefraction = true;
8521                         r_refdef.view = myview;
8522
8523                         r_refdef.view.clipplane = p->plane;
8524                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8525                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8526
8527                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8528                         {
8529                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8530                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8531                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8532                                 R_RenderView_UpdateViewVectors();
8533                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8534                                 {
8535                                         r_refdef.view.usecustompvs = true;
8536                                         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);
8537                                 }
8538                         }
8539
8540                         PlaneClassify(&r_refdef.view.clipplane);
8541
8542                         R_ResetViewRendering3D();
8543                         R_ClearScreen(r_refdef.fogenabled);
8544                         R_View_Update();
8545                         R_RenderScene();
8546
8547                         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);
8548                         r_waterstate.renderingrefraction = false;
8549                 }
8550                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8551                 {
8552                         r_refdef.view = myview;
8553
8554                         r_refdef.view.clipplane = p->plane;
8555                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8556                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8557
8558                         r_refdef.view.width = r_waterstate.camerawidth;
8559                         r_refdef.view.height = r_waterstate.cameraheight;
8560                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8561                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8562
8563                         if(p->camera_entity)
8564                         {
8565                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8566                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8567                         }
8568
8569                         // reverse the cullface settings for this render
8570                         r_refdef.view.cullface_front = GL_FRONT;
8571                         r_refdef.view.cullface_back = GL_BACK;
8572                         // also reverse the view matrix
8573                         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
8574                         R_RenderView_UpdateViewVectors();
8575                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8576                         {
8577                                 r_refdef.view.usecustompvs = true;
8578                                 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);
8579                         }
8580                         
8581                         // camera needs no clipplane
8582                         r_refdef.view.useclipplane = false;
8583
8584                         PlaneClassify(&r_refdef.view.clipplane);
8585
8586                         R_ResetViewRendering3D();
8587                         R_ClearScreen(r_refdef.fogenabled);
8588                         R_View_Update();
8589                         R_RenderScene();
8590
8591                         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);
8592                         r_waterstate.renderingrefraction = false;
8593                 }
8594
8595         }
8596         r_waterstate.renderingscene = false;
8597         r_refdef.view = originalview;
8598         R_ResetViewRendering3D();
8599         R_ClearScreen(r_refdef.fogenabled);
8600         R_View_Update();
8601         return;
8602 error:
8603         r_refdef.view = originalview;
8604         r_waterstate.renderingscene = false;
8605         Cvar_SetValueQuick(&r_water, 0);
8606         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8607         return;
8608 }
8609
8610 void R_Bloom_StartFrame(void)
8611 {
8612         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8613
8614         switch(vid.renderpath)
8615         {
8616         case RENDERPATH_GL20:
8617         case RENDERPATH_CGGL:
8618         case RENDERPATH_D3D9:
8619         case RENDERPATH_D3D10:
8620         case RENDERPATH_D3D11:
8621                 break;
8622         case RENDERPATH_GL13:
8623         case RENDERPATH_GL11:
8624                 return;
8625         }
8626
8627         // set bloomwidth and bloomheight to the bloom resolution that will be
8628         // used (often less than the screen resolution for faster rendering)
8629         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8630         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8631         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8632         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8633         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8634
8635         // calculate desired texture sizes
8636         if (vid.support.arb_texture_non_power_of_two)
8637         {
8638                 screentexturewidth = r_refdef.view.width;
8639                 screentextureheight = r_refdef.view.height;
8640                 bloomtexturewidth = r_bloomstate.bloomwidth;
8641                 bloomtextureheight = r_bloomstate.bloomheight;
8642         }
8643         else
8644         {
8645                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8646                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8647                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8648                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8649         }
8650
8651         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))
8652         {
8653                 Cvar_SetValueQuick(&r_hdr, 0);
8654                 Cvar_SetValueQuick(&r_bloom, 0);
8655                 Cvar_SetValueQuick(&r_motionblur, 0);
8656                 Cvar_SetValueQuick(&r_damageblur, 0);
8657         }
8658
8659         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)))
8660                 screentexturewidth = screentextureheight = 0;
8661         if (!r_hdr.integer && !r_bloom.integer)
8662                 bloomtexturewidth = bloomtextureheight = 0;
8663
8664         // allocate textures as needed
8665         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8666         {
8667                 if (r_bloomstate.texture_screen)
8668                         R_FreeTexture(r_bloomstate.texture_screen);
8669                 r_bloomstate.texture_screen = NULL;
8670                 r_bloomstate.screentexturewidth = screentexturewidth;
8671                 r_bloomstate.screentextureheight = screentextureheight;
8672                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8673                         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);
8674         }
8675         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8676         {
8677                 if (r_bloomstate.texture_bloom)
8678                         R_FreeTexture(r_bloomstate.texture_bloom);
8679                 r_bloomstate.texture_bloom = NULL;
8680                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8681                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8682                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8683                         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);
8684         }
8685
8686         // when doing a reduced render (HDR) we want to use a smaller area
8687         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8688         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8689         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8690         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8691         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8692
8693         // set up a texcoord array for the full resolution screen image
8694         // (we have to keep this around to copy back during final render)
8695         r_bloomstate.screentexcoord2f[0] = 0;
8696         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8697         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8698         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8699         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8700         r_bloomstate.screentexcoord2f[5] = 0;
8701         r_bloomstate.screentexcoord2f[6] = 0;
8702         r_bloomstate.screentexcoord2f[7] = 0;
8703
8704         // set up a texcoord array for the reduced resolution bloom image
8705         // (which will be additive blended over the screen image)
8706         r_bloomstate.bloomtexcoord2f[0] = 0;
8707         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8708         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8709         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8710         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8711         r_bloomstate.bloomtexcoord2f[5] = 0;
8712         r_bloomstate.bloomtexcoord2f[6] = 0;
8713         r_bloomstate.bloomtexcoord2f[7] = 0;
8714
8715         switch(vid.renderpath)
8716         {
8717         case RENDERPATH_GL11:
8718         case RENDERPATH_GL13:
8719         case RENDERPATH_GL20:
8720         case RENDERPATH_CGGL:
8721                 break;
8722         case RENDERPATH_D3D9:
8723         case RENDERPATH_D3D10:
8724         case RENDERPATH_D3D11:
8725                 {
8726                         int i;
8727                         for (i = 0;i < 4;i++)
8728                         {
8729                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8730                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8731                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8732                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8733                         }
8734                 }
8735                 break;
8736         }
8737
8738         if (r_hdr.integer || r_bloom.integer)
8739         {
8740                 r_bloomstate.enabled = true;
8741                 r_bloomstate.hdr = r_hdr.integer != 0;
8742         }
8743
8744         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);
8745 }
8746
8747 void R_Bloom_CopyBloomTexture(float colorscale)
8748 {
8749         r_refdef.stats.bloom++;
8750
8751         // scale down screen texture to the bloom texture size
8752         CHECKGLERROR
8753         R_SetViewport(&r_bloomstate.viewport);
8754         GL_BlendFunc(GL_ONE, GL_ZERO);
8755         GL_Color(colorscale, colorscale, colorscale, 1);
8756         // 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...
8757         switch(vid.renderpath)
8758         {
8759         case RENDERPATH_GL11:
8760         case RENDERPATH_GL13:
8761         case RENDERPATH_GL20:
8762         case RENDERPATH_CGGL:
8763                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8764                 break;
8765         case RENDERPATH_D3D9:
8766         case RENDERPATH_D3D10:
8767         case RENDERPATH_D3D11:
8768                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8769                 break;
8770         }
8771         // TODO: do boxfilter scale-down in shader?
8772         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8773         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8774         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8775
8776         // we now have a bloom image in the framebuffer
8777         // copy it into the bloom image texture for later processing
8778         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);
8779         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8780 }
8781
8782 void R_Bloom_CopyHDRTexture(void)
8783 {
8784         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);
8785         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8786 }
8787
8788 void R_Bloom_MakeTexture(void)
8789 {
8790         int x, range, dir;
8791         float xoffset, yoffset, r, brighten;
8792
8793         r_refdef.stats.bloom++;
8794
8795         R_ResetViewRendering2D();
8796
8797         // we have a bloom image in the framebuffer
8798         CHECKGLERROR
8799         R_SetViewport(&r_bloomstate.viewport);
8800
8801         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8802         {
8803                 x *= 2;
8804                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8805                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8806                 GL_Color(r,r,r,1);
8807                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8808                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8809                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8810                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8811
8812                 // copy the vertically blurred bloom view to a texture
8813                 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);
8814                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8815         }
8816
8817         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8818         brighten = r_bloom_brighten.value;
8819         if (r_hdr.integer)
8820                 brighten *= r_hdr_range.value;
8821         brighten = sqrt(brighten);
8822         if(range >= 1)
8823                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8824         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8825
8826         for (dir = 0;dir < 2;dir++)
8827         {
8828                 // blend on at multiple vertical offsets to achieve a vertical blur
8829                 // TODO: do offset blends using GLSL
8830                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8831                 GL_BlendFunc(GL_ONE, GL_ZERO);
8832                 for (x = -range;x <= range;x++)
8833                 {
8834                         if (!dir){xoffset = 0;yoffset = x;}
8835                         else {xoffset = x;yoffset = 0;}
8836                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8837                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8838                         // compute a texcoord array with the specified x and y offset
8839                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8840                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8841                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8842                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8843                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8844                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8845                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8846                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8847                         // this r value looks like a 'dot' particle, fading sharply to
8848                         // black at the edges
8849                         // (probably not realistic but looks good enough)
8850                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8851                         //r = brighten/(range*2+1);
8852                         r = brighten / (range * 2 + 1);
8853                         if(range >= 1)
8854                                 r *= (1 - x*x/(float)(range*range));
8855                         GL_Color(r, r, r, 1);
8856                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8857                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8858                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8859                         GL_BlendFunc(GL_ONE, GL_ONE);
8860                 }
8861
8862                 // copy the vertically blurred bloom view to a texture
8863                 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);
8864                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8865         }
8866 }
8867
8868 void R_HDR_RenderBloomTexture(void)
8869 {
8870         int oldwidth, oldheight;
8871         float oldcolorscale;
8872
8873         oldcolorscale = r_refdef.view.colorscale;
8874         oldwidth = r_refdef.view.width;
8875         oldheight = r_refdef.view.height;
8876         r_refdef.view.width = r_bloomstate.bloomwidth;
8877         r_refdef.view.height = r_bloomstate.bloomheight;
8878
8879         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8880         // TODO: add exposure compensation features
8881         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8882
8883         r_refdef.view.showdebug = false;
8884         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8885
8886         R_ResetViewRendering3D();
8887
8888         R_ClearScreen(r_refdef.fogenabled);
8889         if (r_timereport_active)
8890                 R_TimeReport("HDRclear");
8891
8892         R_View_Update();
8893         if (r_timereport_active)
8894                 R_TimeReport("visibility");
8895
8896         // only do secondary renders with HDR if r_hdr is 2 or higher
8897         r_waterstate.numwaterplanes = 0;
8898         if (r_waterstate.enabled && r_hdr.integer >= 2)
8899                 R_RenderWaterPlanes();
8900
8901         r_refdef.view.showdebug = true;
8902         R_RenderScene();
8903         r_waterstate.numwaterplanes = 0;
8904
8905         R_ResetViewRendering2D();
8906
8907         R_Bloom_CopyHDRTexture();
8908         R_Bloom_MakeTexture();
8909
8910         // restore the view settings
8911         r_refdef.view.width = oldwidth;
8912         r_refdef.view.height = oldheight;
8913         r_refdef.view.colorscale = oldcolorscale;
8914
8915         R_ResetViewRendering3D();
8916
8917         R_ClearScreen(r_refdef.fogenabled);
8918         if (r_timereport_active)
8919                 R_TimeReport("viewclear");
8920 }
8921
8922 static void R_BlendView(void)
8923 {
8924         unsigned int permutation;
8925         float uservecs[4][4];
8926
8927         switch (vid.renderpath)
8928         {
8929         case RENDERPATH_GL20:
8930         case RENDERPATH_CGGL:
8931         case RENDERPATH_D3D9:
8932         case RENDERPATH_D3D10:
8933         case RENDERPATH_D3D11:
8934                 permutation =
8935                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8936                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8937                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8938                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8939                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8940
8941                 if (r_bloomstate.texture_screen)
8942                 {
8943                         // make sure the buffer is available
8944                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8945
8946                         R_ResetViewRendering2D();
8947
8948                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8949                         {
8950                                 // declare variables
8951                                 float speed;
8952                                 static float avgspeed;
8953
8954                                 speed = VectorLength(cl.movement_velocity);
8955
8956                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8957                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8958
8959                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8960                                 speed = bound(0, speed, 1);
8961                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8962
8963                                 // calculate values into a standard alpha
8964                                 cl.motionbluralpha = 1 - exp(-
8965                                                 (
8966                                                  (r_motionblur.value * speed / 80)
8967                                                  +
8968                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8969                                                 )
8970                                                 /
8971                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8972                                            );
8973
8974                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8975                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8976                                 // apply the blur
8977                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8978                                 {
8979                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8980                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8981                                         switch(vid.renderpath)
8982                                         {
8983                                         case RENDERPATH_GL11:
8984                                         case RENDERPATH_GL13:
8985                                         case RENDERPATH_GL20:
8986                                         case RENDERPATH_CGGL:
8987                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8988                                                 break;
8989                                         case RENDERPATH_D3D9:
8990                                         case RENDERPATH_D3D10:
8991                                         case RENDERPATH_D3D11:
8992                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8993                                                 break;
8994                                         }
8995                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8996                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8997                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8998                                 }
8999                         }
9000
9001                         // copy view into the screen texture
9002                         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);
9003                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9004                 }
9005                 else if (!r_bloomstate.texture_bloom)
9006                 {
9007                         // we may still have to do view tint...
9008                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9009                         {
9010                                 // apply a color tint to the whole view
9011                                 R_ResetViewRendering2D();
9012                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9013                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9014                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9015                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9016                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9017                         }
9018                         break; // no screen processing, no bloom, skip it
9019                 }
9020
9021                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9022                 {
9023                         // render simple bloom effect
9024                         // copy the screen and shrink it and darken it for the bloom process
9025                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9026                         // make the bloom texture
9027                         R_Bloom_MakeTexture();
9028                 }
9029
9030 #if _MSC_VER >= 1400
9031 #define sscanf sscanf_s
9032 #endif
9033                 memset(uservecs, 0, sizeof(uservecs));
9034                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9035                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9036                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9037                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9038
9039                 R_ResetViewRendering2D();
9040                 GL_Color(1, 1, 1, 1);
9041                 GL_BlendFunc(GL_ONE, GL_ZERO);
9042
9043                 switch(vid.renderpath)
9044                 {
9045                 case RENDERPATH_GL20:
9046                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9047                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9048                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9049                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9050                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9051                         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]);
9052                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9053                         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]);
9054                         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]);
9055                         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]);
9056                         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]);
9057                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9058                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9059                         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);
9060                         break;
9061                 case RENDERPATH_CGGL:
9062 #ifdef SUPPORTCG
9063                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9064                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9065                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9066                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9067                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9068                         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
9069                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9070                         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
9071                         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
9072                         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
9073                         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
9074                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9075                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9076                         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);
9077 #endif
9078                         break;
9079                 case RENDERPATH_D3D9:
9080 #ifdef SUPPORTD3D
9081                         // 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...
9082                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9083                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9084                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9085                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9086                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9087                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9088                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9089                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9090                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9091                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9092                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9093                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9094                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9095                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9096 #endif
9097                         break;
9098                 case RENDERPATH_D3D10:
9099                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9100                         break;
9101                 case RENDERPATH_D3D11:
9102                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9103                         break;
9104                 default:
9105                         break;
9106                 }
9107                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9108                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9109                 break;
9110         case RENDERPATH_GL13:
9111         case RENDERPATH_GL11:
9112                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9113                 {
9114                         // apply a color tint to the whole view
9115                         R_ResetViewRendering2D();
9116                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9117                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9118                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9119                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9120                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9121                 }
9122                 break;
9123         }
9124 }
9125
9126 matrix4x4_t r_waterscrollmatrix;
9127
9128 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9129 {
9130         if (r_refdef.fog_density)
9131         {
9132                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9133                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9134                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9135
9136                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9137                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9138                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9139                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9140
9141                 {
9142                         vec3_t fogvec;
9143                         VectorCopy(r_refdef.fogcolor, fogvec);
9144                         //   color.rgb *= ContrastBoost * SceneBrightness;
9145                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9146                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9147                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9148                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9149                 }
9150         }
9151 }
9152
9153 void R_UpdateVariables(void)
9154 {
9155         R_Textures_Frame();
9156
9157         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9158
9159         r_refdef.farclip = r_farclip_base.value;
9160         if (r_refdef.scene.worldmodel)
9161                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9162         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9163
9164         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9165                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9166         r_refdef.polygonfactor = 0;
9167         r_refdef.polygonoffset = 0;
9168         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9169         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9170
9171         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9172         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9173         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9174         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9175         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9176         if (r_showsurfaces.integer)
9177         {
9178                 r_refdef.scene.rtworld = false;
9179                 r_refdef.scene.rtworldshadows = false;
9180                 r_refdef.scene.rtdlight = false;
9181                 r_refdef.scene.rtdlightshadows = false;
9182                 r_refdef.lightmapintensity = 0;
9183         }
9184
9185         if (gamemode == GAME_NEHAHRA)
9186         {
9187                 if (gl_fogenable.integer)
9188                 {
9189                         r_refdef.oldgl_fogenable = true;
9190                         r_refdef.fog_density = gl_fogdensity.value;
9191                         r_refdef.fog_red = gl_fogred.value;
9192                         r_refdef.fog_green = gl_foggreen.value;
9193                         r_refdef.fog_blue = gl_fogblue.value;
9194                         r_refdef.fog_alpha = 1;
9195                         r_refdef.fog_start = 0;
9196                         r_refdef.fog_end = gl_skyclip.value;
9197                         r_refdef.fog_height = 1<<30;
9198                         r_refdef.fog_fadedepth = 128;
9199                 }
9200                 else if (r_refdef.oldgl_fogenable)
9201                 {
9202                         r_refdef.oldgl_fogenable = false;
9203                         r_refdef.fog_density = 0;
9204                         r_refdef.fog_red = 0;
9205                         r_refdef.fog_green = 0;
9206                         r_refdef.fog_blue = 0;
9207                         r_refdef.fog_alpha = 0;
9208                         r_refdef.fog_start = 0;
9209                         r_refdef.fog_end = 0;
9210                         r_refdef.fog_height = 1<<30;
9211                         r_refdef.fog_fadedepth = 128;
9212                 }
9213         }
9214
9215         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9216         r_refdef.fog_start = max(0, r_refdef.fog_start);
9217         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9218
9219         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9220
9221         if (r_refdef.fog_density && r_drawfog.integer)
9222         {
9223                 r_refdef.fogenabled = true;
9224                 // this is the point where the fog reaches 0.9986 alpha, which we
9225                 // consider a good enough cutoff point for the texture
9226                 // (0.9986 * 256 == 255.6)
9227                 if (r_fog_exp2.integer)
9228                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9229                 else
9230                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9231                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9232                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9233                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9234                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9235                         R_BuildFogHeightTexture();
9236                 // fog color was already set
9237                 // update the fog texture
9238                 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)
9239                         R_BuildFogTexture();
9240                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9241                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9242         }
9243         else
9244                 r_refdef.fogenabled = false;
9245
9246         switch(vid.renderpath)
9247         {
9248         case RENDERPATH_GL20:
9249         case RENDERPATH_CGGL:
9250         case RENDERPATH_D3D9:
9251         case RENDERPATH_D3D10:
9252         case RENDERPATH_D3D11:
9253                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9254                 {
9255                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9256                         {
9257                                 // build GLSL gamma texture
9258 #define RAMPWIDTH 256
9259                                 unsigned short ramp[RAMPWIDTH * 3];
9260                                 unsigned char rampbgr[RAMPWIDTH][4];
9261                                 int i;
9262
9263                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9264
9265                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9266                                 for(i = 0; i < RAMPWIDTH; ++i)
9267                                 {
9268                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9269                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9270                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9271                                         rampbgr[i][3] = 0;
9272                                 }
9273                                 if (r_texture_gammaramps)
9274                                 {
9275                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9276                                 }
9277                                 else
9278                                 {
9279                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9280                                 }
9281                         }
9282                 }
9283                 else
9284                 {
9285                         // remove GLSL gamma texture
9286                 }
9287                 break;
9288         case RENDERPATH_GL13:
9289         case RENDERPATH_GL11:
9290                 break;
9291         }
9292 }
9293
9294 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9295 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9296 /*
9297 ================
9298 R_SelectScene
9299 ================
9300 */
9301 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9302         if( scenetype != r_currentscenetype ) {
9303                 // store the old scenetype
9304                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9305                 r_currentscenetype = scenetype;
9306                 // move in the new scene
9307                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9308         }
9309 }
9310
9311 /*
9312 ================
9313 R_GetScenePointer
9314 ================
9315 */
9316 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9317 {
9318         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9319         if( scenetype == r_currentscenetype ) {
9320                 return &r_refdef.scene;
9321         } else {
9322                 return &r_scenes_store[ scenetype ];
9323         }
9324 }
9325
9326 /*
9327 ================
9328 R_RenderView
9329 ================
9330 */
9331 void R_RenderView(void)
9332 {
9333         if (r_timereport_active)
9334                 R_TimeReport("start");
9335         r_textureframe++; // used only by R_GetCurrentTexture
9336         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9337
9338         if (!r_drawentities.integer)
9339                 r_refdef.scene.numentities = 0;
9340
9341         R_AnimCache_ClearCache();
9342         R_FrameData_NewFrame();
9343
9344         if (r_refdef.view.isoverlay)
9345         {
9346                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9347                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9348                 R_TimeReport("depthclear");
9349
9350                 r_refdef.view.showdebug = false;
9351
9352                 r_waterstate.enabled = false;
9353                 r_waterstate.numwaterplanes = 0;
9354
9355                 R_RenderScene();
9356
9357                 CHECKGLERROR
9358                 return;
9359         }
9360
9361         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9362                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9363
9364         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9365
9366         R_RenderView_UpdateViewVectors();
9367
9368         R_Shadow_UpdateWorldLightSelection();
9369
9370         R_Bloom_StartFrame();
9371         R_Water_StartFrame();
9372
9373         CHECKGLERROR
9374         if (r_timereport_active)
9375                 R_TimeReport("viewsetup");
9376
9377         R_ResetViewRendering3D();
9378
9379         if (r_refdef.view.clear || r_refdef.fogenabled)
9380         {
9381                 R_ClearScreen(r_refdef.fogenabled);
9382                 if (r_timereport_active)
9383                         R_TimeReport("viewclear");
9384         }
9385         r_refdef.view.clear = true;
9386
9387         // this produces a bloom texture to be used in R_BlendView() later
9388         if (r_hdr.integer && r_bloomstate.bloomwidth)
9389         {
9390                 R_HDR_RenderBloomTexture();
9391                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9392                 r_textureframe++; // used only by R_GetCurrentTexture
9393         }
9394
9395         r_refdef.view.showdebug = true;
9396
9397         R_View_Update();
9398         if (r_timereport_active)
9399                 R_TimeReport("visibility");
9400
9401         r_waterstate.numwaterplanes = 0;
9402         if (r_waterstate.enabled)
9403                 R_RenderWaterPlanes();
9404
9405         R_RenderScene();
9406         r_waterstate.numwaterplanes = 0;
9407
9408         R_BlendView();
9409         if (r_timereport_active)
9410                 R_TimeReport("blendview");
9411
9412         GL_Scissor(0, 0, vid.width, vid.height);
9413         GL_ScissorTest(false);
9414         CHECKGLERROR
9415 }
9416
9417 void R_RenderWaterPlanes(void)
9418 {
9419         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9420         {
9421                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9422                 if (r_timereport_active)
9423                         R_TimeReport("waterworld");
9424         }
9425
9426         // don't let sound skip if going slow
9427         if (r_refdef.scene.extraupdate)
9428                 S_ExtraUpdate ();
9429
9430         R_DrawModelsAddWaterPlanes();
9431         if (r_timereport_active)
9432                 R_TimeReport("watermodels");
9433
9434         if (r_waterstate.numwaterplanes)
9435         {
9436                 R_Water_ProcessPlanes();
9437                 if (r_timereport_active)
9438                         R_TimeReport("waterscenes");
9439         }
9440 }
9441
9442 extern void R_DrawLightningBeams (void);
9443 extern void VM_CL_AddPolygonsToMeshQueue (void);
9444 extern void R_DrawPortals (void);
9445 extern cvar_t cl_locs_show;
9446 static void R_DrawLocs(void);
9447 static void R_DrawEntityBBoxes(void);
9448 static void R_DrawModelDecals(void);
9449 extern void R_DrawModelShadows(void);
9450 extern void R_DrawModelShadowMaps(void);
9451 extern cvar_t cl_decals_newsystem;
9452 extern qboolean r_shadow_usingdeferredprepass;
9453 void R_RenderScene(void)
9454 {
9455         qboolean shadowmapping = false;
9456
9457         if (r_timereport_active)
9458                 R_TimeReport("beginscene");
9459
9460         r_refdef.stats.renders++;
9461
9462         R_UpdateFogColor();
9463
9464         // don't let sound skip if going slow
9465         if (r_refdef.scene.extraupdate)
9466                 S_ExtraUpdate ();
9467
9468         R_MeshQueue_BeginScene();
9469
9470         R_SkyStartFrame();
9471
9472         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);
9473
9474         if (r_timereport_active)
9475                 R_TimeReport("skystartframe");
9476
9477         if (cl.csqc_vidvars.drawworld)
9478         {
9479                 // don't let sound skip if going slow
9480                 if (r_refdef.scene.extraupdate)
9481                         S_ExtraUpdate ();
9482
9483                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9484                 {
9485                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9486                         if (r_timereport_active)
9487                                 R_TimeReport("worldsky");
9488                 }
9489
9490                 if (R_DrawBrushModelsSky() && r_timereport_active)
9491                         R_TimeReport("bmodelsky");
9492
9493                 if (skyrendermasked && skyrenderlater)
9494                 {
9495                         // we have to force off the water clipping plane while rendering sky
9496                         R_SetupView(false);
9497                         R_Sky();
9498                         R_SetupView(true);
9499                         if (r_timereport_active)
9500                                 R_TimeReport("sky");
9501                 }
9502         }
9503
9504         R_AnimCache_CacheVisibleEntities();
9505         if (r_timereport_active)
9506                 R_TimeReport("animation");
9507
9508         R_Shadow_PrepareLights();
9509         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9510                 R_Shadow_PrepareModelShadows();
9511         if (r_timereport_active)
9512                 R_TimeReport("preparelights");
9513
9514         if (R_Shadow_ShadowMappingEnabled())
9515                 shadowmapping = true;
9516
9517         if (r_shadow_usingdeferredprepass)
9518                 R_Shadow_DrawPrepass();
9519
9520         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9521         {
9522                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9523                 if (r_timereport_active)
9524                         R_TimeReport("worlddepth");
9525         }
9526         if (r_depthfirst.integer >= 2)
9527         {
9528                 R_DrawModelsDepth();
9529                 if (r_timereport_active)
9530                         R_TimeReport("modeldepth");
9531         }
9532
9533         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9534         {
9535                 R_DrawModelShadowMaps();
9536                 R_ResetViewRendering3D();
9537                 // don't let sound skip if going slow
9538                 if (r_refdef.scene.extraupdate)
9539                         S_ExtraUpdate ();
9540         }
9541
9542         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9543         {
9544                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9545                 if (r_timereport_active)
9546                         R_TimeReport("world");
9547         }
9548
9549         // don't let sound skip if going slow
9550         if (r_refdef.scene.extraupdate)
9551                 S_ExtraUpdate ();
9552
9553         R_DrawModels();
9554         if (r_timereport_active)
9555                 R_TimeReport("models");
9556
9557         // don't let sound skip if going slow
9558         if (r_refdef.scene.extraupdate)
9559                 S_ExtraUpdate ();
9560
9561         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9562         {
9563                 R_DrawModelShadows();
9564                 R_ResetViewRendering3D();
9565                 // don't let sound skip if going slow
9566                 if (r_refdef.scene.extraupdate)
9567                         S_ExtraUpdate ();
9568         }
9569
9570         if (!r_shadow_usingdeferredprepass)
9571         {
9572                 R_Shadow_DrawLights();
9573                 if (r_timereport_active)
9574                         R_TimeReport("rtlights");
9575         }
9576
9577         // don't let sound skip if going slow
9578         if (r_refdef.scene.extraupdate)
9579                 S_ExtraUpdate ();
9580
9581         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9582         {
9583                 R_DrawModelShadows();
9584                 R_ResetViewRendering3D();
9585                 // don't let sound skip if going slow
9586                 if (r_refdef.scene.extraupdate)
9587                         S_ExtraUpdate ();
9588         }
9589
9590         if (cl.csqc_vidvars.drawworld)
9591         {
9592                 if (cl_decals_newsystem.integer)
9593                 {
9594                         R_DrawModelDecals();
9595                         if (r_timereport_active)
9596                                 R_TimeReport("modeldecals");
9597                 }
9598                 else
9599                 {
9600                         R_DrawDecals();
9601                         if (r_timereport_active)
9602                                 R_TimeReport("decals");
9603                 }
9604
9605                 R_DrawParticles();
9606                 if (r_timereport_active)
9607                         R_TimeReport("particles");
9608
9609                 R_DrawExplosions();
9610                 if (r_timereport_active)
9611                         R_TimeReport("explosions");
9612
9613                 R_DrawLightningBeams();
9614                 if (r_timereport_active)
9615                         R_TimeReport("lightning");
9616         }
9617
9618         VM_CL_AddPolygonsToMeshQueue();
9619
9620         if (r_refdef.view.showdebug)
9621         {
9622                 if (cl_locs_show.integer)
9623                 {
9624                         R_DrawLocs();
9625                         if (r_timereport_active)
9626                                 R_TimeReport("showlocs");
9627                 }
9628
9629                 if (r_drawportals.integer)
9630                 {
9631                         R_DrawPortals();
9632                         if (r_timereport_active)
9633                                 R_TimeReport("portals");
9634                 }
9635
9636                 if (r_showbboxes.value > 0)
9637                 {
9638                         R_DrawEntityBBoxes();
9639                         if (r_timereport_active)
9640                                 R_TimeReport("bboxes");
9641                 }
9642         }
9643
9644         R_MeshQueue_RenderTransparent();
9645         if (r_timereport_active)
9646                 R_TimeReport("drawtrans");
9647
9648         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))
9649         {
9650                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9651                 if (r_timereport_active)
9652                         R_TimeReport("worlddebug");
9653                 R_DrawModelsDebug();
9654                 if (r_timereport_active)
9655                         R_TimeReport("modeldebug");
9656         }
9657
9658         if (cl.csqc_vidvars.drawworld)
9659         {
9660                 R_Shadow_DrawCoronas();
9661                 if (r_timereport_active)
9662                         R_TimeReport("coronas");
9663         }
9664
9665         // don't let sound skip if going slow
9666         if (r_refdef.scene.extraupdate)
9667                 S_ExtraUpdate ();
9668
9669         R_ResetViewRendering2D();
9670 }
9671
9672 static const unsigned short bboxelements[36] =
9673 {
9674         5, 1, 3, 5, 3, 7,
9675         6, 2, 0, 6, 0, 4,
9676         7, 3, 2, 7, 2, 6,
9677         4, 0, 1, 4, 1, 5,
9678         4, 5, 7, 4, 7, 6,
9679         1, 0, 2, 1, 2, 3,
9680 };
9681
9682 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9683 {
9684         int i;
9685         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9686
9687         RSurf_ActiveWorldEntity();
9688
9689         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9690         GL_DepthMask(false);
9691         GL_DepthRange(0, 1);
9692         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9693         R_Mesh_ResetTextureState();
9694
9695         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9696         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9697         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9698         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9699         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9700         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9701         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9702         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9703         R_FillColors(color4f, 8, cr, cg, cb, ca);
9704         if (r_refdef.fogenabled)
9705         {
9706                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9707                 {
9708                         f1 = RSurf_FogVertex(v);
9709                         f2 = 1 - f1;
9710                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9711                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9712                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9713                 }
9714         }
9715         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9716         R_Mesh_ResetTextureState();
9717         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9718         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9719 }
9720
9721 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9722 {
9723         int i;
9724         float color[4];
9725         prvm_edict_t *edict;
9726         prvm_prog_t *prog_save = prog;
9727
9728         // this function draws bounding boxes of server entities
9729         if (!sv.active)
9730                 return;
9731
9732         GL_CullFace(GL_NONE);
9733         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9734
9735         prog = 0;
9736         SV_VM_Begin();
9737         for (i = 0;i < numsurfaces;i++)
9738         {
9739                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9740                 switch ((int)edict->fields.server->solid)
9741                 {
9742                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9743                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9744                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9745                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9746                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9747                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9748                 }
9749                 color[3] *= r_showbboxes.value;
9750                 color[3] = bound(0, color[3], 1);
9751                 GL_DepthTest(!r_showdisabledepthtest.integer);
9752                 GL_CullFace(r_refdef.view.cullface_front);
9753                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9754         }
9755         SV_VM_End();
9756         prog = prog_save;
9757 }
9758
9759 static void R_DrawEntityBBoxes(void)
9760 {
9761         int i;
9762         prvm_edict_t *edict;
9763         vec3_t center;
9764         prvm_prog_t *prog_save = prog;
9765
9766         // this function draws bounding boxes of server entities
9767         if (!sv.active)
9768                 return;
9769
9770         prog = 0;
9771         SV_VM_Begin();
9772         for (i = 0;i < prog->num_edicts;i++)
9773         {
9774                 edict = PRVM_EDICT_NUM(i);
9775                 if (edict->priv.server->free)
9776                         continue;
9777                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9778                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9779                         continue;
9780                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9781                         continue;
9782                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9783                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9784         }
9785         SV_VM_End();
9786         prog = prog_save;
9787 }
9788
9789 static const int nomodelelement3i[24] =
9790 {
9791         5, 2, 0,
9792         5, 1, 2,
9793         5, 0, 3,
9794         5, 3, 1,
9795         0, 2, 4,
9796         2, 1, 4,
9797         3, 0, 4,
9798         1, 3, 4
9799 };
9800
9801 static const unsigned short nomodelelement3s[24] =
9802 {
9803         5, 2, 0,
9804         5, 1, 2,
9805         5, 0, 3,
9806         5, 3, 1,
9807         0, 2, 4,
9808         2, 1, 4,
9809         3, 0, 4,
9810         1, 3, 4
9811 };
9812
9813 static const float nomodelvertex3f[6*3] =
9814 {
9815         -16,   0,   0,
9816          16,   0,   0,
9817           0, -16,   0,
9818           0,  16,   0,
9819           0,   0, -16,
9820           0,   0,  16
9821 };
9822
9823 static const float nomodelcolor4f[6*4] =
9824 {
9825         0.0f, 0.0f, 0.5f, 1.0f,
9826         0.0f, 0.0f, 0.5f, 1.0f,
9827         0.0f, 0.5f, 0.0f, 1.0f,
9828         0.0f, 0.5f, 0.0f, 1.0f,
9829         0.5f, 0.0f, 0.0f, 1.0f,
9830         0.5f, 0.0f, 0.0f, 1.0f
9831 };
9832
9833 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9834 {
9835         int i;
9836         float f1, f2, *c;
9837         float color4f[6*4];
9838
9839         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);
9840
9841         // this is only called once per entity so numsurfaces is always 1, and
9842         // surfacelist is always {0}, so this code does not handle batches
9843
9844         if (rsurface.ent_flags & RENDER_ADDITIVE)
9845         {
9846                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9847                 GL_DepthMask(false);
9848         }
9849         else if (rsurface.colormod[3] < 1)
9850         {
9851                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9852                 GL_DepthMask(false);
9853         }
9854         else
9855         {
9856                 GL_BlendFunc(GL_ONE, GL_ZERO);
9857                 GL_DepthMask(true);
9858         }
9859         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9860         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9861         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9862         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9863         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9864         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9865         for (i = 0, c = color4f;i < 6;i++, c += 4)
9866         {
9867                 c[0] *= rsurface.colormod[0];
9868                 c[1] *= rsurface.colormod[1];
9869                 c[2] *= rsurface.colormod[2];
9870                 c[3] *= rsurface.colormod[3];
9871         }
9872         if (r_refdef.fogenabled)
9873         {
9874                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9875                 {
9876                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9877                         f2 = 1 - f1;
9878                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9879                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9880                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9881                 }
9882         }
9883         R_Mesh_ResetTextureState();
9884         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9885         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9886 }
9887
9888 void R_DrawNoModel(entity_render_t *ent)
9889 {
9890         vec3_t org;
9891         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9892         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9893                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9894         else
9895                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9896 }
9897
9898 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9899 {
9900         vec3_t right1, right2, diff, normal;
9901
9902         VectorSubtract (org2, org1, normal);
9903
9904         // calculate 'right' vector for start
9905         VectorSubtract (r_refdef.view.origin, org1, diff);
9906         CrossProduct (normal, diff, right1);
9907         VectorNormalize (right1);
9908
9909         // calculate 'right' vector for end
9910         VectorSubtract (r_refdef.view.origin, org2, diff);
9911         CrossProduct (normal, diff, right2);
9912         VectorNormalize (right2);
9913
9914         vert[ 0] = org1[0] + width * right1[0];
9915         vert[ 1] = org1[1] + width * right1[1];
9916         vert[ 2] = org1[2] + width * right1[2];
9917         vert[ 3] = org1[0] - width * right1[0];
9918         vert[ 4] = org1[1] - width * right1[1];
9919         vert[ 5] = org1[2] - width * right1[2];
9920         vert[ 6] = org2[0] - width * right2[0];
9921         vert[ 7] = org2[1] - width * right2[1];
9922         vert[ 8] = org2[2] - width * right2[2];
9923         vert[ 9] = org2[0] + width * right2[0];
9924         vert[10] = org2[1] + width * right2[1];
9925         vert[11] = org2[2] + width * right2[2];
9926 }
9927
9928 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)
9929 {
9930         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9931         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9932         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9933         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9934         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9935         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9936         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9937         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9938         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9939         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9940         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9941         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9942 }
9943
9944 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9945 {
9946         int i;
9947         float *vertex3f;
9948         float v[3];
9949         VectorSet(v, x, y, z);
9950         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9951                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9952                         break;
9953         if (i == mesh->numvertices)
9954         {
9955                 if (mesh->numvertices < mesh->maxvertices)
9956                 {
9957                         VectorCopy(v, vertex3f);
9958                         mesh->numvertices++;
9959                 }
9960                 return mesh->numvertices;
9961         }
9962         else
9963                 return i;
9964 }
9965
9966 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9967 {
9968         int i;
9969         int *e, element[3];
9970         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9971         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9972         e = mesh->element3i + mesh->numtriangles * 3;
9973         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9974         {
9975                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9976                 if (mesh->numtriangles < mesh->maxtriangles)
9977                 {
9978                         *e++ = element[0];
9979                         *e++ = element[1];
9980                         *e++ = element[2];
9981                         mesh->numtriangles++;
9982                 }
9983                 element[1] = element[2];
9984         }
9985 }
9986
9987 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9988 {
9989         int i;
9990         int *e, element[3];
9991         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9992         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9993         e = mesh->element3i + mesh->numtriangles * 3;
9994         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9995         {
9996                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9997                 if (mesh->numtriangles < mesh->maxtriangles)
9998                 {
9999                         *e++ = element[0];
10000                         *e++ = element[1];
10001                         *e++ = element[2];
10002                         mesh->numtriangles++;
10003                 }
10004                 element[1] = element[2];
10005         }
10006 }
10007
10008 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10009 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10010 {
10011         int planenum, planenum2;
10012         int w;
10013         int tempnumpoints;
10014         mplane_t *plane, *plane2;
10015         double maxdist;
10016         double temppoints[2][256*3];
10017         // figure out how large a bounding box we need to properly compute this brush
10018         maxdist = 0;
10019         for (w = 0;w < numplanes;w++)
10020                 maxdist = max(maxdist, fabs(planes[w].dist));
10021         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10022         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10023         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10024         {
10025                 w = 0;
10026                 tempnumpoints = 4;
10027                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10028                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10029                 {
10030                         if (planenum2 == planenum)
10031                                 continue;
10032                         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);
10033                         w = !w;
10034                 }
10035                 if (tempnumpoints < 3)
10036                         continue;
10037                 // generate elements forming a triangle fan for this polygon
10038                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10039         }
10040 }
10041
10042 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)
10043 {
10044         texturelayer_t *layer;
10045         layer = t->currentlayers + t->currentnumlayers++;
10046         layer->type = type;
10047         layer->depthmask = depthmask;
10048         layer->blendfunc1 = blendfunc1;
10049         layer->blendfunc2 = blendfunc2;
10050         layer->texture = texture;
10051         layer->texmatrix = *matrix;
10052         layer->color[0] = r;
10053         layer->color[1] = g;
10054         layer->color[2] = b;
10055         layer->color[3] = a;
10056 }
10057
10058 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10059 {
10060         if(parms[0] == 0 && parms[1] == 0)
10061                 return false;
10062         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10063                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10064                         return false;
10065         return true;
10066 }
10067
10068 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10069 {
10070         double index, f;
10071         index = parms[2] + r_refdef.scene.time * parms[3];
10072         index -= floor(index);
10073         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10074         {
10075         default:
10076         case Q3WAVEFUNC_NONE:
10077         case Q3WAVEFUNC_NOISE:
10078         case Q3WAVEFUNC_COUNT:
10079                 f = 0;
10080                 break;
10081         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10082         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10083         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10084         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10085         case Q3WAVEFUNC_TRIANGLE:
10086                 index *= 4;
10087                 f = index - floor(index);
10088                 if (index < 1)
10089                         f = f;
10090                 else if (index < 2)
10091                         f = 1 - f;
10092                 else if (index < 3)
10093                         f = -f;
10094                 else
10095                         f = -(1 - f);
10096                 break;
10097         }
10098         f = parms[0] + parms[1] * f;
10099         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10100                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10101         return (float) f;
10102 }
10103
10104 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10105 {
10106         int w, h, idx;
10107         float f;
10108         float tcmat[12];
10109         matrix4x4_t matrix, temp;
10110         switch(tcmod->tcmod)
10111         {
10112                 case Q3TCMOD_COUNT:
10113                 case Q3TCMOD_NONE:
10114                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10115                                 matrix = r_waterscrollmatrix;
10116                         else
10117                                 matrix = identitymatrix;
10118                         break;
10119                 case Q3TCMOD_ENTITYTRANSLATE:
10120                         // this is used in Q3 to allow the gamecode to control texcoord
10121                         // scrolling on the entity, which is not supported in darkplaces yet.
10122                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10123                         break;
10124                 case Q3TCMOD_ROTATE:
10125                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10126                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10127                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10128                         break;
10129                 case Q3TCMOD_SCALE:
10130                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10131                         break;
10132                 case Q3TCMOD_SCROLL:
10133                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10134                         break;
10135                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10136                         w = (int) tcmod->parms[0];
10137                         h = (int) tcmod->parms[1];
10138                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10139                         f = f - floor(f);
10140                         idx = (int) floor(f * w * h);
10141                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10142                         break;
10143                 case Q3TCMOD_STRETCH:
10144                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10145                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10146                         break;
10147                 case Q3TCMOD_TRANSFORM:
10148                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10149                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10150                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10151                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10152                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10153                         break;
10154                 case Q3TCMOD_TURBULENT:
10155                         // this is handled in the RSurf_PrepareVertices function
10156                         matrix = identitymatrix;
10157                         break;
10158         }
10159         temp = *texmatrix;
10160         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10161 }
10162
10163 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10164 {
10165         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10166         char name[MAX_QPATH];
10167         skinframe_t *skinframe;
10168         unsigned char pixels[296*194];
10169         strlcpy(cache->name, skinname, sizeof(cache->name));
10170         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10171         if (developer_loading.integer)
10172                 Con_Printf("loading %s\n", name);
10173         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10174         if (!skinframe || !skinframe->base)
10175         {
10176                 unsigned char *f;
10177                 fs_offset_t filesize;
10178                 skinframe = NULL;
10179                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10180                 if (f)
10181                 {
10182                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10183                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10184                         Mem_Free(f);
10185                 }
10186         }
10187         cache->skinframe = skinframe;
10188 }
10189
10190 texture_t *R_GetCurrentTexture(texture_t *t)
10191 {
10192         int i;
10193         const entity_render_t *ent = rsurface.entity;
10194         dp_model_t *model = ent->model;
10195         q3shaderinfo_layer_tcmod_t *tcmod;
10196
10197         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10198                 return t->currentframe;
10199         t->update_lastrenderframe = r_textureframe;
10200         t->update_lastrenderentity = (void *)ent;
10201
10202         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10203                 t->camera_entity = ent->entitynumber;
10204         else
10205                 t->camera_entity = 0;
10206
10207         // switch to an alternate material if this is a q1bsp animated material
10208         {
10209                 texture_t *texture = t;
10210                 int s = rsurface.ent_skinnum;
10211                 if ((unsigned int)s >= (unsigned int)model->numskins)
10212                         s = 0;
10213                 if (model->skinscenes)
10214                 {
10215                         if (model->skinscenes[s].framecount > 1)
10216                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10217                         else
10218                                 s = model->skinscenes[s].firstframe;
10219                 }
10220                 if (s > 0)
10221                         t = t + s * model->num_surfaces;
10222                 if (t->animated)
10223                 {
10224                         // use an alternate animation if the entity's frame is not 0,
10225                         // and only if the texture has an alternate animation
10226                         if (rsurface.ent_alttextures && t->anim_total[1])
10227                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10228                         else
10229                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10230                 }
10231                 texture->currentframe = t;
10232         }
10233
10234         // update currentskinframe to be a qw skin or animation frame
10235         if (rsurface.ent_qwskin >= 0)
10236         {
10237                 i = rsurface.ent_qwskin;
10238                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10239                 {
10240                         r_qwskincache_size = cl.maxclients;
10241                         if (r_qwskincache)
10242                                 Mem_Free(r_qwskincache);
10243                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10244                 }
10245                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10246                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10247                 t->currentskinframe = r_qwskincache[i].skinframe;
10248                 if (t->currentskinframe == NULL)
10249                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10250         }
10251         else if (t->numskinframes >= 2)
10252                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10253         if (t->backgroundnumskinframes >= 2)
10254                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10255
10256         t->currentmaterialflags = t->basematerialflags;
10257         t->currentalpha = rsurface.colormod[3];
10258         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10259                 t->currentalpha *= r_wateralpha.value;
10260         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10261                 t->currentalpha *= t->r_water_wateralpha;
10262         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10263                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10264         if (!(rsurface.ent_flags & RENDER_LIGHT))
10265                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10266         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10267         {
10268                 // pick a model lighting mode
10269                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10270                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10271                 else
10272                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10273         }
10274         if (rsurface.ent_flags & RENDER_ADDITIVE)
10275                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10276         else if (t->currentalpha < 1)
10277                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10278         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10279                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10280         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10281                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10282         if (t->backgroundnumskinframes)
10283                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10284         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10285         {
10286                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10287                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10288         }
10289         else
10290                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10291         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10292                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10293
10294         // there is no tcmod
10295         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10296         {
10297                 t->currenttexmatrix = r_waterscrollmatrix;
10298                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10299         }
10300         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10301         {
10302                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10303                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10304         }
10305
10306         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10307                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10308         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10309                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10310
10311         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10312         if (t->currentskinframe->qpixels)
10313                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10314         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10315         if (!t->basetexture)
10316                 t->basetexture = r_texture_notexture;
10317         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10318         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10319         t->nmaptexture = t->currentskinframe->nmap;
10320         if (!t->nmaptexture)
10321                 t->nmaptexture = r_texture_blanknormalmap;
10322         t->glosstexture = r_texture_black;
10323         t->glowtexture = t->currentskinframe->glow;
10324         t->fogtexture = t->currentskinframe->fog;
10325         t->reflectmasktexture = t->currentskinframe->reflect;
10326         if (t->backgroundnumskinframes)
10327         {
10328                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10329                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10330                 t->backgroundglosstexture = r_texture_black;
10331                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10332                 if (!t->backgroundnmaptexture)
10333                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10334         }
10335         else
10336         {
10337                 t->backgroundbasetexture = r_texture_white;
10338                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10339                 t->backgroundglosstexture = r_texture_black;
10340                 t->backgroundglowtexture = NULL;
10341         }
10342         t->specularpower = r_shadow_glossexponent.value;
10343         // TODO: store reference values for these in the texture?
10344         t->specularscale = 0;
10345         if (r_shadow_gloss.integer > 0)
10346         {
10347                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10348                 {
10349                         if (r_shadow_glossintensity.value > 0)
10350                         {
10351                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10352                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10353                                 t->specularscale = r_shadow_glossintensity.value;
10354                         }
10355                 }
10356                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10357                 {
10358                         t->glosstexture = r_texture_white;
10359                         t->backgroundglosstexture = r_texture_white;
10360                         t->specularscale = r_shadow_gloss2intensity.value;
10361                         t->specularpower = r_shadow_gloss2exponent.value;
10362                 }
10363         }
10364         t->specularscale *= t->specularscalemod;
10365         t->specularpower *= t->specularpowermod;
10366
10367         // lightmaps mode looks bad with dlights using actual texturing, so turn
10368         // off the colormap and glossmap, but leave the normalmap on as it still
10369         // accurately represents the shading involved
10370         if (gl_lightmaps.integer)
10371         {
10372                 t->basetexture = r_texture_grey128;
10373                 t->pantstexture = r_texture_black;
10374                 t->shirttexture = r_texture_black;
10375                 t->nmaptexture = r_texture_blanknormalmap;
10376                 t->glosstexture = r_texture_black;
10377                 t->glowtexture = NULL;
10378                 t->fogtexture = NULL;
10379                 t->reflectmasktexture = NULL;
10380                 t->backgroundbasetexture = NULL;
10381                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10382                 t->backgroundglosstexture = r_texture_black;
10383                 t->backgroundglowtexture = NULL;
10384                 t->specularscale = 0;
10385                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10386         }
10387
10388         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10389         VectorClear(t->dlightcolor);
10390         t->currentnumlayers = 0;
10391         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10392         {
10393                 int blendfunc1, blendfunc2;
10394                 qboolean depthmask;
10395                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10396                 {
10397                         blendfunc1 = GL_SRC_ALPHA;
10398                         blendfunc2 = GL_ONE;
10399                 }
10400                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10401                 {
10402                         blendfunc1 = GL_SRC_ALPHA;
10403                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10404                 }
10405                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10406                 {
10407                         blendfunc1 = t->customblendfunc[0];
10408                         blendfunc2 = t->customblendfunc[1];
10409                 }
10410                 else
10411                 {
10412                         blendfunc1 = GL_ONE;
10413                         blendfunc2 = GL_ZERO;
10414                 }
10415                 // don't colormod evilblend textures
10416                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10417                         VectorSet(t->lightmapcolor, 1, 1, 1);
10418                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10419                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10420                 {
10421                         // fullbright is not affected by r_refdef.lightmapintensity
10422                         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]);
10423                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10424                                 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]);
10425                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10426                                 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]);
10427                 }
10428                 else
10429                 {
10430                         vec3_t ambientcolor;
10431                         float colorscale;
10432                         // set the color tint used for lights affecting this surface
10433                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10434                         colorscale = 2;
10435                         // q3bsp has no lightmap updates, so the lightstylevalue that
10436                         // would normally be baked into the lightmap must be
10437                         // applied to the color
10438                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10439                         if (model->type == mod_brushq3)
10440                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10441                         colorscale *= r_refdef.lightmapintensity;
10442                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10443                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10444                         // basic lit geometry
10445                         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]);
10446                         // add pants/shirt if needed
10447                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10448                                 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]);
10449                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10450                                 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]);
10451                         // now add ambient passes if needed
10452                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10453                         {
10454                                 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]);
10455                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10456                                         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]);
10457                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10458                                         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]);
10459                         }
10460                 }
10461                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10462                         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]);
10463                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10464                 {
10465                         // if this is opaque use alpha blend which will darken the earlier
10466                         // passes cheaply.
10467                         //
10468                         // if this is an alpha blended material, all the earlier passes
10469                         // were darkened by fog already, so we only need to add the fog
10470                         // color ontop through the fog mask texture
10471                         //
10472                         // if this is an additive blended material, all the earlier passes
10473                         // were darkened by fog already, and we should not add fog color
10474                         // (because the background was not darkened, there is no fog color
10475                         // that was lost behind it).
10476                         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]);
10477                 }
10478         }
10479
10480         return t->currentframe;
10481 }
10482
10483 rsurfacestate_t rsurface;
10484
10485 void R_Mesh_ResizeArrays(int newvertices)
10486 {
10487         unsigned char *base;
10488         size_t size;
10489         if (rsurface.array_size >= newvertices)
10490                 return;
10491         if (rsurface.array_base)
10492                 Mem_Free(rsurface.array_base);
10493         rsurface.array_size = (newvertices + 1023) & ~1023;
10494         size = 0;
10495         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10496         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10497         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10498         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10499         size += rsurface.array_size * sizeof(float[3]);
10500         size += rsurface.array_size * sizeof(float[3]);
10501         size += rsurface.array_size * sizeof(float[3]);
10502         size += rsurface.array_size * sizeof(float[3]);
10503         size += rsurface.array_size * sizeof(float[3]);
10504         size += rsurface.array_size * sizeof(float[3]);
10505         size += rsurface.array_size * sizeof(float[3]);
10506         size += rsurface.array_size * sizeof(float[3]);
10507         size += rsurface.array_size * sizeof(float[4]);
10508         size += rsurface.array_size * sizeof(float[2]);
10509         size += rsurface.array_size * sizeof(float[2]);
10510         size += rsurface.array_size * sizeof(float[4]);
10511         size += rsurface.array_size * sizeof(int[3]);
10512         size += rsurface.array_size * sizeof(unsigned short[3]);
10513         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10514         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10515         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10516         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10517         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10518         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10519         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10520         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10521         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10522         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10523         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10524         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10525         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10526         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10527         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10528         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10529         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10530         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10531         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10532 }
10533
10534 void RSurf_ActiveWorldEntity(void)
10535 {
10536         dp_model_t *model = r_refdef.scene.worldmodel;
10537         //if (rsurface.entity == r_refdef.scene.worldentity)
10538         //      return;
10539         rsurface.entity = r_refdef.scene.worldentity;
10540         rsurface.skeleton = NULL;
10541         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10542         rsurface.ent_skinnum = 0;
10543         rsurface.ent_qwskin = -1;
10544         rsurface.ent_shadertime = 0;
10545         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10546         if (rsurface.array_size < model->surfmesh.num_vertices)
10547                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10548         rsurface.matrix = identitymatrix;
10549         rsurface.inversematrix = identitymatrix;
10550         rsurface.matrixscale = 1;
10551         rsurface.inversematrixscale = 1;
10552         R_EntityMatrix(&identitymatrix);
10553         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10554         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10555         rsurface.fograngerecip = r_refdef.fograngerecip;
10556         rsurface.fogheightfade = r_refdef.fogheightfade;
10557         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10558         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10559         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10560         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10561         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10562         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10563         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10564         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10565         rsurface.colormod[3] = 1;
10566         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);
10567         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10568         rsurface.frameblend[0].lerp = 1;
10569         rsurface.ent_alttextures = false;
10570         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10571         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10572         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10573         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10574         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10575         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10576         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10577         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10578         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10579         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10580         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10581         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10582         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10583         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10584         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10585         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10586         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10587         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10588         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10589         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10590         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10591         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10592         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10593         rsurface.modelelement3i = model->surfmesh.data_element3i;
10594         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10595         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10596         rsurface.modelelement3s = model->surfmesh.data_element3s;
10597         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10598         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10599         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10600         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10601         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10602         rsurface.modelsurfaces = model->data_surfaces;
10603         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10604         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10605         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10606         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10607         rsurface.modelgeneratedvertex = false;
10608         rsurface.batchgeneratedvertex = false;
10609         rsurface.batchfirstvertex = 0;
10610         rsurface.batchnumvertices = 0;
10611         rsurface.batchfirsttriangle = 0;
10612         rsurface.batchnumtriangles = 0;
10613         rsurface.batchvertex3f  = NULL;
10614         rsurface.batchvertex3f_vertexbuffer = NULL;
10615         rsurface.batchvertex3f_bufferoffset = 0;
10616         rsurface.batchsvector3f = NULL;
10617         rsurface.batchsvector3f_vertexbuffer = NULL;
10618         rsurface.batchsvector3f_bufferoffset = 0;
10619         rsurface.batchtvector3f = NULL;
10620         rsurface.batchtvector3f_vertexbuffer = NULL;
10621         rsurface.batchtvector3f_bufferoffset = 0;
10622         rsurface.batchnormal3f  = NULL;
10623         rsurface.batchnormal3f_vertexbuffer = NULL;
10624         rsurface.batchnormal3f_bufferoffset = 0;
10625         rsurface.batchlightmapcolor4f = NULL;
10626         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10627         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10628         rsurface.batchtexcoordtexture2f = NULL;
10629         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10630         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10631         rsurface.batchtexcoordlightmap2f = NULL;
10632         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10633         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10634         rsurface.batchvertexmesh = NULL;
10635         rsurface.batchvertexmeshbuffer = NULL;
10636         rsurface.batchvertexposition = NULL;
10637         rsurface.batchvertexpositionbuffer = NULL;
10638         rsurface.batchelement3i = NULL;
10639         rsurface.batchelement3i_indexbuffer = NULL;
10640         rsurface.batchelement3i_bufferoffset = 0;
10641         rsurface.batchelement3s = NULL;
10642         rsurface.batchelement3s_indexbuffer = NULL;
10643         rsurface.batchelement3s_bufferoffset = 0;
10644         rsurface.passcolor4f = NULL;
10645         rsurface.passcolor4f_vertexbuffer = NULL;
10646         rsurface.passcolor4f_bufferoffset = 0;
10647 }
10648
10649 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10650 {
10651         dp_model_t *model = ent->model;
10652         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10653         //      return;
10654         rsurface.entity = (entity_render_t *)ent;
10655         rsurface.skeleton = ent->skeleton;
10656         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10657         rsurface.ent_skinnum = ent->skinnum;
10658         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;
10659         rsurface.ent_shadertime = ent->shadertime;
10660         rsurface.ent_flags = ent->flags;
10661         if (rsurface.array_size < model->surfmesh.num_vertices)
10662                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10663         rsurface.matrix = ent->matrix;
10664         rsurface.inversematrix = ent->inversematrix;
10665         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10666         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10667         R_EntityMatrix(&rsurface.matrix);
10668         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10669         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10670         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10671         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10672         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10673         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10674         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10675         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10676         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10677         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10678         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10679         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10680         rsurface.colormod[3] = ent->alpha;
10681         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10682         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10683         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10684         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10685         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10686         if (ent->model->brush.submodel && !prepass)
10687         {
10688                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10689                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10690         }
10691         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10692         {
10693                 if (ent->animcache_vertex3f && !r_framedata_failed)
10694                 {
10695                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10696                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10697                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10698                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10699                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10700                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10701                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10702                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10703                 }
10704                 else if (wanttangents)
10705                 {
10706                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10707                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10708                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10709                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10710                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10711                         rsurface.modelvertexmesh = NULL;
10712                         rsurface.modelvertexmeshbuffer = NULL;
10713                         rsurface.modelvertexposition = NULL;
10714                         rsurface.modelvertexpositionbuffer = NULL;
10715                 }
10716                 else if (wantnormals)
10717                 {
10718                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10719                         rsurface.modelsvector3f = NULL;
10720                         rsurface.modeltvector3f = NULL;
10721                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10722                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10723                         rsurface.modelvertexmesh = NULL;
10724                         rsurface.modelvertexmeshbuffer = NULL;
10725                         rsurface.modelvertexposition = NULL;
10726                         rsurface.modelvertexpositionbuffer = NULL;
10727                 }
10728                 else
10729                 {
10730                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10731                         rsurface.modelsvector3f = NULL;
10732                         rsurface.modeltvector3f = NULL;
10733                         rsurface.modelnormal3f = NULL;
10734                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10735                         rsurface.modelvertexmesh = NULL;
10736                         rsurface.modelvertexmeshbuffer = NULL;
10737                         rsurface.modelvertexposition = NULL;
10738                         rsurface.modelvertexpositionbuffer = NULL;
10739                 }
10740                 rsurface.modelvertex3f_vertexbuffer = 0;
10741                 rsurface.modelvertex3f_bufferoffset = 0;
10742                 rsurface.modelsvector3f_vertexbuffer = 0;
10743                 rsurface.modelsvector3f_bufferoffset = 0;
10744                 rsurface.modeltvector3f_vertexbuffer = 0;
10745                 rsurface.modeltvector3f_bufferoffset = 0;
10746                 rsurface.modelnormal3f_vertexbuffer = 0;
10747                 rsurface.modelnormal3f_bufferoffset = 0;
10748                 rsurface.modelgeneratedvertex = true;
10749         }
10750         else
10751         {
10752                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10753                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10754                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10755                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10756                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10757                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10758                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10759                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10760                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10761                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10762                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10763                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10764                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10765                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10766                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10767                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10768                 rsurface.modelgeneratedvertex = false;
10769         }
10770         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10771         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10772         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10773         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10774         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10775         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10776         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10777         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10778         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10779         rsurface.modelelement3i = model->surfmesh.data_element3i;
10780         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10781         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10782         rsurface.modelelement3s = model->surfmesh.data_element3s;
10783         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10784         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10785         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10786         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10787         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10788         rsurface.modelsurfaces = model->data_surfaces;
10789         rsurface.batchgeneratedvertex = false;
10790         rsurface.batchfirstvertex = 0;
10791         rsurface.batchnumvertices = 0;
10792         rsurface.batchfirsttriangle = 0;
10793         rsurface.batchnumtriangles = 0;
10794         rsurface.batchvertex3f  = NULL;
10795         rsurface.batchvertex3f_vertexbuffer = NULL;
10796         rsurface.batchvertex3f_bufferoffset = 0;
10797         rsurface.batchsvector3f = NULL;
10798         rsurface.batchsvector3f_vertexbuffer = NULL;
10799         rsurface.batchsvector3f_bufferoffset = 0;
10800         rsurface.batchtvector3f = NULL;
10801         rsurface.batchtvector3f_vertexbuffer = NULL;
10802         rsurface.batchtvector3f_bufferoffset = 0;
10803         rsurface.batchnormal3f  = NULL;
10804         rsurface.batchnormal3f_vertexbuffer = NULL;
10805         rsurface.batchnormal3f_bufferoffset = 0;
10806         rsurface.batchlightmapcolor4f = NULL;
10807         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10808         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10809         rsurface.batchtexcoordtexture2f = NULL;
10810         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10811         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10812         rsurface.batchtexcoordlightmap2f = NULL;
10813         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10814         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10815         rsurface.batchvertexmesh = NULL;
10816         rsurface.batchvertexmeshbuffer = NULL;
10817         rsurface.batchvertexposition = NULL;
10818         rsurface.batchvertexpositionbuffer = NULL;
10819         rsurface.batchelement3i = NULL;
10820         rsurface.batchelement3i_indexbuffer = NULL;
10821         rsurface.batchelement3i_bufferoffset = 0;
10822         rsurface.batchelement3s = NULL;
10823         rsurface.batchelement3s_indexbuffer = NULL;
10824         rsurface.batchelement3s_bufferoffset = 0;
10825         rsurface.passcolor4f = NULL;
10826         rsurface.passcolor4f_vertexbuffer = NULL;
10827         rsurface.passcolor4f_bufferoffset = 0;
10828 }
10829
10830 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)
10831 {
10832         int i;
10833
10834         rsurface.entity = r_refdef.scene.worldentity;
10835         rsurface.skeleton = NULL;
10836         rsurface.ent_skinnum = 0;
10837         rsurface.ent_qwskin = -1;
10838         rsurface.ent_shadertime = shadertime;
10839         rsurface.ent_flags = entflags;
10840         rsurface.modelnumvertices = numvertices;
10841         rsurface.modelnumtriangles = numtriangles;
10842         if (rsurface.array_size < rsurface.modelnumvertices)
10843                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10844         rsurface.matrix = *matrix;
10845         rsurface.inversematrix = *inversematrix;
10846         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10847         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10848         R_EntityMatrix(&rsurface.matrix);
10849         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10850         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10851         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10852         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10853         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10854         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10855         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10856         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10857         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10858         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10859         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10860         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10861         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);
10862         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10863         rsurface.frameblend[0].lerp = 1;
10864         rsurface.ent_alttextures = false;
10865         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10866         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10867         if (wanttangents)
10868         {
10869                 rsurface.modelvertex3f = vertex3f;
10870                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10871                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10872                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10873         }
10874         else if (wantnormals)
10875         {
10876                 rsurface.modelvertex3f = vertex3f;
10877                 rsurface.modelsvector3f = NULL;
10878                 rsurface.modeltvector3f = NULL;
10879                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10880         }
10881         else
10882         {
10883                 rsurface.modelvertex3f = vertex3f;
10884                 rsurface.modelsvector3f = NULL;
10885                 rsurface.modeltvector3f = NULL;
10886                 rsurface.modelnormal3f = NULL;
10887         }
10888         rsurface.modelvertexmesh = NULL;
10889         rsurface.modelvertexmeshbuffer = NULL;
10890         rsurface.modelvertexposition = NULL;
10891         rsurface.modelvertexpositionbuffer = NULL;
10892         rsurface.modelvertex3f_vertexbuffer = 0;
10893         rsurface.modelvertex3f_bufferoffset = 0;
10894         rsurface.modelsvector3f_vertexbuffer = 0;
10895         rsurface.modelsvector3f_bufferoffset = 0;
10896         rsurface.modeltvector3f_vertexbuffer = 0;
10897         rsurface.modeltvector3f_bufferoffset = 0;
10898         rsurface.modelnormal3f_vertexbuffer = 0;
10899         rsurface.modelnormal3f_bufferoffset = 0;
10900         rsurface.modelgeneratedvertex = true;
10901         rsurface.modellightmapcolor4f  = color4f;
10902         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10903         rsurface.modellightmapcolor4f_bufferoffset = 0;
10904         rsurface.modeltexcoordtexture2f  = texcoord2f;
10905         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10906         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10907         rsurface.modeltexcoordlightmap2f  = NULL;
10908         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10909         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10910         rsurface.modelelement3i = element3i;
10911         rsurface.modelelement3i_indexbuffer = NULL;
10912         rsurface.modelelement3i_bufferoffset = 0;
10913         rsurface.modelelement3s = element3s;
10914         rsurface.modelelement3s_indexbuffer = NULL;
10915         rsurface.modelelement3s_bufferoffset = 0;
10916         rsurface.modellightmapoffsets = NULL;
10917         rsurface.modelsurfaces = NULL;
10918         rsurface.batchgeneratedvertex = false;
10919         rsurface.batchfirstvertex = 0;
10920         rsurface.batchnumvertices = 0;
10921         rsurface.batchfirsttriangle = 0;
10922         rsurface.batchnumtriangles = 0;
10923         rsurface.batchvertex3f  = NULL;
10924         rsurface.batchvertex3f_vertexbuffer = NULL;
10925         rsurface.batchvertex3f_bufferoffset = 0;
10926         rsurface.batchsvector3f = NULL;
10927         rsurface.batchsvector3f_vertexbuffer = NULL;
10928         rsurface.batchsvector3f_bufferoffset = 0;
10929         rsurface.batchtvector3f = NULL;
10930         rsurface.batchtvector3f_vertexbuffer = NULL;
10931         rsurface.batchtvector3f_bufferoffset = 0;
10932         rsurface.batchnormal3f  = NULL;
10933         rsurface.batchnormal3f_vertexbuffer = NULL;
10934         rsurface.batchnormal3f_bufferoffset = 0;
10935         rsurface.batchlightmapcolor4f = NULL;
10936         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10937         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10938         rsurface.batchtexcoordtexture2f = NULL;
10939         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10940         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10941         rsurface.batchtexcoordlightmap2f = NULL;
10942         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10943         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10944         rsurface.batchvertexmesh = NULL;
10945         rsurface.batchvertexmeshbuffer = NULL;
10946         rsurface.batchvertexposition = NULL;
10947         rsurface.batchvertexpositionbuffer = NULL;
10948         rsurface.batchelement3i = NULL;
10949         rsurface.batchelement3i_indexbuffer = NULL;
10950         rsurface.batchelement3i_bufferoffset = 0;
10951         rsurface.batchelement3s = NULL;
10952         rsurface.batchelement3s_indexbuffer = NULL;
10953         rsurface.batchelement3s_bufferoffset = 0;
10954         rsurface.passcolor4f = NULL;
10955         rsurface.passcolor4f_vertexbuffer = NULL;
10956         rsurface.passcolor4f_bufferoffset = 0;
10957
10958         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10959         {
10960                 if ((wantnormals || wanttangents) && !normal3f)
10961                 {
10962                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10963                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10964                 }
10965                 if (wanttangents && !svector3f)
10966                 {
10967                         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);
10968                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10969                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10970                 }
10971         }
10972
10973         // now convert arrays into vertexmesh structs
10974         for (i = 0;i < numvertices;i++)
10975         {
10976                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10977                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10978                 if (rsurface.modelsvector3f)
10979                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10980                 if (rsurface.modeltvector3f)
10981                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10982                 if (rsurface.modelnormal3f)
10983                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10984                 if (rsurface.modellightmapcolor4f)
10985                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10986                 if (rsurface.modeltexcoordtexture2f)
10987                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10988                 if (rsurface.modeltexcoordlightmap2f)
10989                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10990         }
10991 }
10992
10993 float RSurf_FogPoint(const float *v)
10994 {
10995         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10996         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10997         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10998         float FogHeightFade = r_refdef.fogheightfade;
10999         float fogfrac;
11000         unsigned int fogmasktableindex;
11001         if (r_refdef.fogplaneviewabove)
11002                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11003         else
11004                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11005         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11006         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11007 }
11008
11009 float RSurf_FogVertex(const float *v)
11010 {
11011         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11012         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11013         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11014         float FogHeightFade = rsurface.fogheightfade;
11015         float fogfrac;
11016         unsigned int fogmasktableindex;
11017         if (r_refdef.fogplaneviewabove)
11018                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11019         else
11020                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11021         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11022         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11023 }
11024
11025 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11026 {
11027         int i;
11028         for (i = 0;i < numelements;i++)
11029                 outelement3i[i] = inelement3i[i] + adjust;
11030 }
11031
11032 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11033 extern cvar_t gl_vbo;
11034 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11035 {
11036         int deformindex;
11037         int firsttriangle;
11038         int numtriangles;
11039         int firstvertex;
11040         int endvertex;
11041         int numvertices;
11042         int surfacefirsttriangle;
11043         int surfacenumtriangles;
11044         int surfacefirstvertex;
11045         int surfaceendvertex;
11046         int surfacenumvertices;
11047         int surfaceadjustvertex;
11048         int needsupdate;
11049         int i, j;
11050         qboolean gaps;
11051         qboolean dynamicvertex;
11052         float amplitude;
11053         float animpos;
11054         float scale;
11055         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11056         float waveparms[4];
11057         q3shaderinfo_deform_t *deform;
11058         const msurface_t *surface, *firstsurface;
11059         r_vertexposition_t *vertexposition;
11060         r_vertexmesh_t *vertexmesh;
11061         if (!texturenumsurfaces)
11062                 return;
11063         // find vertex range of this surface batch
11064         gaps = false;
11065         firstsurface = texturesurfacelist[0];
11066         firsttriangle = firstsurface->num_firsttriangle;
11067         numtriangles = 0;
11068         firstvertex = endvertex = firstsurface->num_firstvertex;
11069         for (i = 0;i < texturenumsurfaces;i++)
11070         {
11071                 surface = texturesurfacelist[i];
11072                 if (surface != firstsurface + i)
11073                         gaps = true;
11074                 surfacefirstvertex = surface->num_firstvertex;
11075                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11076                 surfacenumtriangles = surface->num_triangles;
11077                 if (firstvertex > surfacefirstvertex)
11078                         firstvertex = surfacefirstvertex;
11079                 if (endvertex < surfaceendvertex)
11080                         endvertex = surfaceendvertex;
11081                 numtriangles += surfacenumtriangles;
11082         }
11083         if (!numtriangles)
11084                 return;
11085
11086         // we now know the vertex range used, and if there are any gaps in it
11087         rsurface.batchfirstvertex = firstvertex;
11088         rsurface.batchnumvertices = endvertex - firstvertex;
11089         rsurface.batchfirsttriangle = firsttriangle;
11090         rsurface.batchnumtriangles = numtriangles;
11091
11092         // this variable holds flags for which properties have been updated that
11093         // may require regenerating vertexmesh or vertexposition arrays...
11094         needsupdate = 0;
11095
11096         // check if any dynamic vertex processing must occur
11097         dynamicvertex = false;
11098
11099         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11100                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11101         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11102         {
11103                 switch (deform->deform)
11104                 {
11105                 default:
11106                 case Q3DEFORM_PROJECTIONSHADOW:
11107                 case Q3DEFORM_TEXT0:
11108                 case Q3DEFORM_TEXT1:
11109                 case Q3DEFORM_TEXT2:
11110                 case Q3DEFORM_TEXT3:
11111                 case Q3DEFORM_TEXT4:
11112                 case Q3DEFORM_TEXT5:
11113                 case Q3DEFORM_TEXT6:
11114                 case Q3DEFORM_TEXT7:
11115                 case Q3DEFORM_NONE:
11116                         break;
11117                 case Q3DEFORM_AUTOSPRITE:
11118                         dynamicvertex = true;
11119                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11120                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11121                         break;
11122                 case Q3DEFORM_AUTOSPRITE2:
11123                         dynamicvertex = true;
11124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11125                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11126                         break;
11127                 case Q3DEFORM_NORMAL:
11128                         dynamicvertex = true;
11129                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11130                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11131                         break;
11132                 case Q3DEFORM_WAVE:
11133                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11134                                 break; // if wavefunc is a nop, ignore this transform
11135                         dynamicvertex = true;
11136                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11137                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11138                         break;
11139                 case Q3DEFORM_BULGE:
11140                         dynamicvertex = true;
11141                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11142                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11143                         break;
11144                 case Q3DEFORM_MOVE:
11145                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11146                                 break; // if wavefunc is a nop, ignore this transform
11147                         dynamicvertex = true;
11148                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11149                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11150                         break;
11151                 }
11152         }
11153         switch(rsurface.texture->tcgen.tcgen)
11154         {
11155         default:
11156         case Q3TCGEN_TEXTURE:
11157                 break;
11158         case Q3TCGEN_LIGHTMAP:
11159                 dynamicvertex = true;
11160                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11161                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11162                 break;
11163         case Q3TCGEN_VECTOR:
11164                 dynamicvertex = true;
11165                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11166                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11167                 break;
11168         case Q3TCGEN_ENVIRONMENT:
11169                 dynamicvertex = true;
11170                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11171                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11172                 break;
11173         }
11174         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11175         {
11176                 dynamicvertex = true;
11177                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11178                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11179         }
11180
11181         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11182         {
11183                 dynamicvertex = true;
11184                 batchneed |= BATCHNEED_NOGAPS;
11185                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11186         }
11187
11188         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11189         {
11190                 dynamicvertex = true;
11191                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11192                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11193         }
11194
11195         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11196         {
11197                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11198                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11199                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11200                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11201                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11202                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11203                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11204         }
11205
11206         // when the model data has no vertex buffer (dynamic mesh), we need to
11207         // eliminate gaps
11208         if (!rsurface.modelvertexmeshbuffer)
11209                 batchneed |= BATCHNEED_NOGAPS;
11210
11211         // if needsupdate, we have to do a dynamic vertex batch for sure
11212         if (needsupdate & batchneed)
11213                 dynamicvertex = true;
11214
11215         // see if we need to build vertexmesh from arrays
11216         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11217                 dynamicvertex = true;
11218
11219         // see if we need to build vertexposition from arrays
11220         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11221                 dynamicvertex = true;
11222
11223         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11224         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11225                 dynamicvertex = true;
11226
11227         // if there is a chance of animated vertex colors, it's a dynamic batch
11228         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11229                 dynamicvertex = true;
11230
11231         rsurface.batchvertex3f = rsurface.modelvertex3f;
11232         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11233         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11234         rsurface.batchsvector3f = rsurface.modelsvector3f;
11235         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11236         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11237         rsurface.batchtvector3f = rsurface.modeltvector3f;
11238         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11239         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11240         rsurface.batchnormal3f = rsurface.modelnormal3f;
11241         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11242         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11243         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11244         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11245         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11246         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11247         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11248         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11249         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11250         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11251         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11252         rsurface.batchvertexposition = rsurface.modelvertexposition;
11253         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11254         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11255         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11256         rsurface.batchelement3i = rsurface.modelelement3i;
11257         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11258         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11259         rsurface.batchelement3s = rsurface.modelelement3s;
11260         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11261         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11262
11263         // if any dynamic vertex processing has to occur in software, we copy the
11264         // entire surface list together before processing to rebase the vertices
11265         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11266         //
11267         // if any gaps exist and we do not have a static vertex buffer, we have to
11268         // copy the surface list together to avoid wasting upload bandwidth on the
11269         // vertices in the gaps.
11270         //
11271         // if gaps exist and we have a static vertex buffer, we still have to
11272         // combine the index buffer ranges into one dynamic index buffer.
11273         //
11274         // in all cases we end up with data that can be drawn in one call.
11275
11276         if (!dynamicvertex)
11277         {
11278                 // static vertex data, just set pointers...
11279                 rsurface.batchgeneratedvertex = false;
11280                 // if there are gaps, we want to build a combined index buffer,
11281                 // otherwise use the original static buffer with an appropriate offset
11282                 if (gaps)
11283                 {
11284                         firsttriangle = 0;
11285                         numtriangles = 0;
11286                         for (i = 0;i < texturenumsurfaces;i++)
11287                         {
11288                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11289                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11290                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11291                                 numtriangles += surfacenumtriangles;
11292                         }
11293                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11294                         rsurface.batchelement3i_indexbuffer = NULL;
11295                         rsurface.batchelement3i_bufferoffset = 0;
11296                         rsurface.batchelement3s = NULL;
11297                         rsurface.batchelement3s_indexbuffer = NULL;
11298                         rsurface.batchelement3s_bufferoffset = 0;
11299                         if (endvertex <= 65536)
11300                         {
11301                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11302                                 for (i = 0;i < numtriangles*3;i++)
11303                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11304                         }
11305                         rsurface.batchfirsttriangle = firsttriangle;
11306                         rsurface.batchnumtriangles = numtriangles;
11307                 }
11308                 return;
11309         }
11310
11311         // something needs software processing, do it for real...
11312         // we only directly handle interleaved array data in this case...
11313         rsurface.batchgeneratedvertex = true;
11314
11315         // now copy the vertex data into a combined array and make an index array
11316         // (this is what Quake3 does all the time)
11317         //if (gaps || rsurface.batchfirstvertex)
11318         {
11319                 rsurface.batchvertexposition = NULL;
11320                 rsurface.batchvertexpositionbuffer = NULL;
11321                 rsurface.batchvertexmesh = NULL;
11322                 rsurface.batchvertexmeshbuffer = NULL;
11323                 rsurface.batchvertex3f = NULL;
11324                 rsurface.batchvertex3f_vertexbuffer = NULL;
11325                 rsurface.batchvertex3f_bufferoffset = 0;
11326                 rsurface.batchsvector3f = NULL;
11327                 rsurface.batchsvector3f_vertexbuffer = NULL;
11328                 rsurface.batchsvector3f_bufferoffset = 0;
11329                 rsurface.batchtvector3f = NULL;
11330                 rsurface.batchtvector3f_vertexbuffer = NULL;
11331                 rsurface.batchtvector3f_bufferoffset = 0;
11332                 rsurface.batchnormal3f = NULL;
11333                 rsurface.batchnormal3f_vertexbuffer = NULL;
11334                 rsurface.batchnormal3f_bufferoffset = 0;
11335                 rsurface.batchlightmapcolor4f = NULL;
11336                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11337                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11338                 rsurface.batchtexcoordtexture2f = NULL;
11339                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11340                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11341                 rsurface.batchtexcoordlightmap2f = NULL;
11342                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11343                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11344                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11345                 rsurface.batchelement3i_indexbuffer = NULL;
11346                 rsurface.batchelement3i_bufferoffset = 0;
11347                 rsurface.batchelement3s = NULL;
11348                 rsurface.batchelement3s_indexbuffer = NULL;
11349                 rsurface.batchelement3s_bufferoffset = 0;
11350                 // we'll only be setting up certain arrays as needed
11351                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11352                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11353                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11354                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11355                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11356                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11357                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11358                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11359                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11360                 {
11361                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11362                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11363                 }
11364                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11365                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11366                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11367                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11368                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11369                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11370                 numvertices = 0;
11371                 numtriangles = 0;
11372                 for (i = 0;i < texturenumsurfaces;i++)
11373                 {
11374                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11375                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11376                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11377                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11378                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11379                         // copy only the data requested
11380                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11381                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11382                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11383                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11384                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11385                         {
11386                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11387                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11388                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11389                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11390                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11391                                 {
11392                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11393                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11394                                 }
11395                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11396                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11397                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11398                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11399                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11400                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11401                         }
11402                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11403                         numvertices += surfacenumvertices;
11404                         numtriangles += surfacenumtriangles;
11405                 }
11406
11407                 // generate a 16bit index array as well if possible
11408                 // (in general, dynamic batches fit)
11409                 if (numvertices <= 65536)
11410                 {
11411                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11412                         for (i = 0;i < numtriangles*3;i++)
11413                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11414                 }
11415
11416                 // since we've copied everything, the batch now starts at 0
11417                 rsurface.batchfirstvertex = 0;
11418                 rsurface.batchnumvertices = numvertices;
11419                 rsurface.batchfirsttriangle = 0;
11420                 rsurface.batchnumtriangles = numtriangles;
11421         }
11422
11423         // q1bsp surfaces rendered in vertex color mode have to have colors
11424         // calculated based on lightstyles
11425         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11426         {
11427                 // generate color arrays for the surfaces in this list
11428                 int c[4];
11429                 int scale;
11430                 int size3;
11431                 const int *offsets;
11432                 const unsigned char *lm;
11433                 numvertices = 0;
11434                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11435                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11436                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11437                 for (i = 0;i < texturenumsurfaces;i++)
11438                 {
11439                         surface = texturesurfacelist[i];
11440                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11441                         surfacenumvertices = surface->num_vertices;
11442                         if (surface->lightmapinfo->samples)
11443                         {
11444                                 for (j = 0;j < surfacenumvertices;j++)
11445                                 {
11446                                         lm = surface->lightmapinfo->samples + offsets[j];
11447                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11448                                         VectorScale(lm, scale, c);
11449                                         if (surface->lightmapinfo->styles[1] != 255)
11450                                         {
11451                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11452                                                 lm += size3;
11453                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11454                                                 VectorMA(c, scale, lm, c);
11455                                                 if (surface->lightmapinfo->styles[2] != 255)
11456                                                 {
11457                                                         lm += size3;
11458                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11459                                                         VectorMA(c, scale, lm, c);
11460                                                         if (surface->lightmapinfo->styles[3] != 255)
11461                                                         {
11462                                                                 lm += size3;
11463                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11464                                                                 VectorMA(c, scale, lm, c);
11465                                                         }
11466                                                 }
11467                                         }
11468                                         c[0] >>= 15;
11469                                         c[1] >>= 15;
11470                                         c[2] >>= 15;
11471                                         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);
11472                                         numvertices++;
11473                                 }
11474                         }
11475                         else
11476                         {
11477                                 for (j = 0;j < surfacenumvertices;j++)
11478                                 {
11479                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11480                                         numvertices++;
11481                                 }
11482                         }
11483                 }
11484         }
11485
11486         // if vertices are deformed (sprite flares and things in maps, possibly
11487         // water waves, bulges and other deformations), modify the copied vertices
11488         // in place
11489         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11490         {
11491                 switch (deform->deform)
11492                 {
11493                 default:
11494                 case Q3DEFORM_PROJECTIONSHADOW:
11495                 case Q3DEFORM_TEXT0:
11496                 case Q3DEFORM_TEXT1:
11497                 case Q3DEFORM_TEXT2:
11498                 case Q3DEFORM_TEXT3:
11499                 case Q3DEFORM_TEXT4:
11500                 case Q3DEFORM_TEXT5:
11501                 case Q3DEFORM_TEXT6:
11502                 case Q3DEFORM_TEXT7:
11503                 case Q3DEFORM_NONE:
11504                         break;
11505                 case Q3DEFORM_AUTOSPRITE:
11506                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11507                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11508                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11509                         VectorNormalize(newforward);
11510                         VectorNormalize(newright);
11511                         VectorNormalize(newup);
11512                         // a single autosprite surface can contain multiple sprites...
11513                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11514                         {
11515                                 VectorClear(center);
11516                                 for (i = 0;i < 4;i++)
11517                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11518                                 VectorScale(center, 0.25f, center);
11519                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11520                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11521                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11522                                 for (i = 0;i < 4;i++)
11523                                 {
11524                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11525                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11526                                 }
11527                         }
11528                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11529                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11530                         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);
11531                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11532                         rsurface.batchvertex3f_vertexbuffer = NULL;
11533                         rsurface.batchvertex3f_bufferoffset = 0;
11534                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11535                         rsurface.batchsvector3f_vertexbuffer = NULL;
11536                         rsurface.batchsvector3f_bufferoffset = 0;
11537                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11538                         rsurface.batchtvector3f_vertexbuffer = NULL;
11539                         rsurface.batchtvector3f_bufferoffset = 0;
11540                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11541                         rsurface.batchnormal3f_vertexbuffer = NULL;
11542                         rsurface.batchnormal3f_bufferoffset = 0;
11543                         break;
11544                 case Q3DEFORM_AUTOSPRITE2:
11545                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11546                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11547                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11548                         VectorNormalize(newforward);
11549                         VectorNormalize(newright);
11550                         VectorNormalize(newup);
11551                         {
11552                                 const float *v1, *v2;
11553                                 vec3_t start, end;
11554                                 float f, l;
11555                                 struct
11556                                 {
11557                                         float length2;
11558                                         const float *v1;
11559                                         const float *v2;
11560                                 }
11561                                 shortest[2];
11562                                 memset(shortest, 0, sizeof(shortest));
11563                                 // a single autosprite surface can contain multiple sprites...
11564                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11565                                 {
11566                                         VectorClear(center);
11567                                         for (i = 0;i < 4;i++)
11568                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11569                                         VectorScale(center, 0.25f, center);
11570                                         // find the two shortest edges, then use them to define the
11571                                         // axis vectors for rotating around the central axis
11572                                         for (i = 0;i < 6;i++)
11573                                         {
11574                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11575                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11576                                                 l = VectorDistance2(v1, v2);
11577                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11578                                                 if (v1[2] != v2[2])
11579                                                         l += (1.0f / 1024.0f);
11580                                                 if (shortest[0].length2 > l || i == 0)
11581                                                 {
11582                                                         shortest[1] = shortest[0];
11583                                                         shortest[0].length2 = l;
11584                                                         shortest[0].v1 = v1;
11585                                                         shortest[0].v2 = v2;
11586                                                 }
11587                                                 else if (shortest[1].length2 > l || i == 1)
11588                                                 {
11589                                                         shortest[1].length2 = l;
11590                                                         shortest[1].v1 = v1;
11591                                                         shortest[1].v2 = v2;
11592                                                 }
11593                                         }
11594                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11595                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11596                                         // this calculates the right vector from the shortest edge
11597                                         // and the up vector from the edge midpoints
11598                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11599                                         VectorNormalize(right);
11600                                         VectorSubtract(end, start, up);
11601                                         VectorNormalize(up);
11602                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11603                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11604                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11605                                         VectorNegate(forward, forward);
11606                                         VectorReflect(forward, 0, up, forward);
11607                                         VectorNormalize(forward);
11608                                         CrossProduct(up, forward, newright);
11609                                         VectorNormalize(newright);
11610                                         // rotate the quad around the up axis vector, this is made
11611                                         // especially easy by the fact we know the quad is flat,
11612                                         // so we only have to subtract the center position and
11613                                         // measure distance along the right vector, and then
11614                                         // multiply that by the newright vector and add back the
11615                                         // center position
11616                                         // we also need to subtract the old position to undo the
11617                                         // displacement from the center, which we do with a
11618                                         // DotProduct, the subtraction/addition of center is also
11619                                         // optimized into DotProducts here
11620                                         l = DotProduct(right, center);
11621                                         for (i = 0;i < 4;i++)
11622                                         {
11623                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11624                                                 f = DotProduct(right, v1) - l;
11625                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11626                                         }
11627                                 }
11628                         }
11629                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11630                         rsurface.batchvertex3f_vertexbuffer = NULL;
11631                         rsurface.batchvertex3f_bufferoffset = 0;
11632                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11633                         {
11634                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11635                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11636                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11637                                 rsurface.batchnormal3f_bufferoffset = 0;
11638                         }
11639                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11640                         {
11641                                 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);
11642                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11643                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11644                                 rsurface.batchsvector3f_bufferoffset = 0;
11645                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11646                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11647                                 rsurface.batchtvector3f_bufferoffset = 0;
11648                         }
11649                         break;
11650                 case Q3DEFORM_NORMAL:
11651                         // deform the normals to make reflections wavey
11652                         for (j = 0;j < rsurface.batchnumvertices;j++)
11653                         {
11654                                 float vertex[3];
11655                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11656                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11657                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11658                                 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]);
11659                                 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]);
11660                                 VectorNormalize(normal);
11661                         }
11662                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11663                         rsurface.batchnormal3f_vertexbuffer = NULL;
11664                         rsurface.batchnormal3f_bufferoffset = 0;
11665                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11666                         {
11667                                 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);
11668                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11669                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11670                                 rsurface.batchsvector3f_bufferoffset = 0;
11671                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11672                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11673                                 rsurface.batchtvector3f_bufferoffset = 0;
11674                         }
11675                         break;
11676                 case Q3DEFORM_WAVE:
11677                         // deform vertex array to make wavey water and flags and such
11678                         waveparms[0] = deform->waveparms[0];
11679                         waveparms[1] = deform->waveparms[1];
11680                         waveparms[2] = deform->waveparms[2];
11681                         waveparms[3] = deform->waveparms[3];
11682                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11683                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11684                         // this is how a divisor of vertex influence on deformation
11685                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11686                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11687                         for (j = 0;j < rsurface.batchnumvertices;j++)
11688                         {
11689                                 // if the wavefunc depends on time, evaluate it per-vertex
11690                                 if (waveparms[3])
11691                                 {
11692                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11693                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11694                                 }
11695                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11696                         }
11697                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11698                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11699                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11700                         rsurface.batchvertex3f_vertexbuffer = NULL;
11701                         rsurface.batchvertex3f_bufferoffset = 0;
11702                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11703                         rsurface.batchnormal3f_vertexbuffer = NULL;
11704                         rsurface.batchnormal3f_bufferoffset = 0;
11705                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11706                         {
11707                                 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);
11708                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11709                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11710                                 rsurface.batchsvector3f_bufferoffset = 0;
11711                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11712                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11713                                 rsurface.batchtvector3f_bufferoffset = 0;
11714                         }
11715                         break;
11716                 case Q3DEFORM_BULGE:
11717                         // deform vertex array to make the surface have moving bulges
11718                         for (j = 0;j < rsurface.batchnumvertices;j++)
11719                         {
11720                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11721                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11722                         }
11723                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11724                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11725                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11726                         rsurface.batchvertex3f_vertexbuffer = NULL;
11727                         rsurface.batchvertex3f_bufferoffset = 0;
11728                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11729                         rsurface.batchnormal3f_vertexbuffer = NULL;
11730                         rsurface.batchnormal3f_bufferoffset = 0;
11731                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11732                         {
11733                                 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);
11734                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11735                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11736                                 rsurface.batchsvector3f_bufferoffset = 0;
11737                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11738                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11739                                 rsurface.batchtvector3f_bufferoffset = 0;
11740                         }
11741                         break;
11742                 case Q3DEFORM_MOVE:
11743                         // deform vertex array
11744                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11745                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11746                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11747                         VectorScale(deform->parms, scale, waveparms);
11748                         for (j = 0;j < rsurface.batchnumvertices;j++)
11749                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11750                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11751                         rsurface.batchvertex3f_vertexbuffer = NULL;
11752                         rsurface.batchvertex3f_bufferoffset = 0;
11753                         break;
11754                 }
11755         }
11756
11757         // generate texcoords based on the chosen texcoord source
11758         switch(rsurface.texture->tcgen.tcgen)
11759         {
11760         default:
11761         case Q3TCGEN_TEXTURE:
11762                 break;
11763         case Q3TCGEN_LIGHTMAP:
11764                 if (rsurface.batchtexcoordlightmap2f)
11765                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11766                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11767                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11768                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11769                 break;
11770         case Q3TCGEN_VECTOR:
11771                 for (j = 0;j < rsurface.batchnumvertices;j++)
11772                 {
11773                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11774                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11775                 }
11776                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11777                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11778                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11779                 break;
11780         case Q3TCGEN_ENVIRONMENT:
11781                 // make environment reflections using a spheremap
11782                 for (j = 0;j < rsurface.batchnumvertices;j++)
11783                 {
11784                         // identical to Q3A's method, but executed in worldspace so
11785                         // carried models can be shiny too
11786
11787                         float viewer[3], d, reflected[3], worldreflected[3];
11788
11789                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11790                         // VectorNormalize(viewer);
11791
11792                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11793
11794                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11795                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11796                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11797                         // note: this is proportinal to viewer, so we can normalize later
11798
11799                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11800                         VectorNormalize(worldreflected);
11801
11802                         // note: this sphere map only uses world x and z!
11803                         // so positive and negative y will LOOK THE SAME.
11804                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11805                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11806                 }
11807                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11808                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11809                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11810                 break;
11811         }
11812         // the only tcmod that needs software vertex processing is turbulent, so
11813         // check for it here and apply the changes if needed
11814         // and we only support that as the first one
11815         // (handling a mixture of turbulent and other tcmods would be problematic
11816         //  without punting it entirely to a software path)
11817         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11818         {
11819                 amplitude = rsurface.texture->tcmods[0].parms[1];
11820                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11821                 for (j = 0;j < rsurface.batchnumvertices;j++)
11822                 {
11823                         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);
11824                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11825                 }
11826                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11827                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11828                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11829         }
11830
11831         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11832         {
11833                 // convert the modified arrays to vertex structs
11834                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11835                 rsurface.batchvertexmeshbuffer = NULL;
11836                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11837                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11838                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11839                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11840                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11841                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11842                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11843                 {
11844                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11845                         {
11846                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11847                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11848                         }
11849                 }
11850                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11851                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11852                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11853                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11854                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11855                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11856                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11857                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11858                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11859         }
11860
11861         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11862         {
11863                 // convert the modified arrays to vertex structs
11864                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11865                 rsurface.batchvertexpositionbuffer = NULL;
11866                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11867                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11868                 else
11869                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11870                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11871         }
11872 }
11873
11874 void RSurf_DrawBatch(void)
11875 {
11876         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);
11877 }
11878
11879 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11880 {
11881         // pick the closest matching water plane
11882         int planeindex, vertexindex, bestplaneindex = -1;
11883         float d, bestd;
11884         vec3_t vert;
11885         const float *v;
11886         r_waterstate_waterplane_t *p;
11887         bestd = 0;
11888         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11889         {
11890                 if(p->camera_entity != rsurface.texture->camera_entity)
11891                         continue;
11892                 d = 0;
11893                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11894                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11895                 {
11896                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11897                         d += fabs(PlaneDiff(vert, &p->plane));
11898                 }
11899                 if (bestd > d || bestplaneindex < 0)
11900                 {
11901                         bestd = d;
11902                         bestplaneindex = planeindex;
11903                 }
11904         }
11905         return bestplaneindex;
11906 }
11907
11908 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11909 {
11910         int i;
11911         for (i = 0;i < rsurface.batchnumvertices;i++)
11912                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11913         rsurface.passcolor4f = rsurface.array_passcolor4f;
11914         rsurface.passcolor4f_vertexbuffer = 0;
11915         rsurface.passcolor4f_bufferoffset = 0;
11916 }
11917
11918 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11919 {
11920         int i;
11921         float f;
11922         const float *v;
11923         const float *c;
11924         float *c2;
11925         if (rsurface.passcolor4f)
11926         {
11927                 // generate color arrays
11928                 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)
11929                 {
11930                         f = RSurf_FogVertex(v);
11931                         c2[0] = c[0] * f;
11932                         c2[1] = c[1] * f;
11933                         c2[2] = c[2] * f;
11934                         c2[3] = c[3];
11935                 }
11936         }
11937         else
11938         {
11939                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11940                 {
11941                         f = RSurf_FogVertex(v);
11942                         c2[0] = f;
11943                         c2[1] = f;
11944                         c2[2] = f;
11945                         c2[3] = 1;
11946                 }
11947         }
11948         rsurface.passcolor4f = rsurface.array_passcolor4f;
11949         rsurface.passcolor4f_vertexbuffer = 0;
11950         rsurface.passcolor4f_bufferoffset = 0;
11951 }
11952
11953 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11954 {
11955         int i;
11956         float f;
11957         const float *v;
11958         const float *c;
11959         float *c2;
11960         if (!rsurface.passcolor4f)
11961                 return;
11962         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)
11963         {
11964                 f = RSurf_FogVertex(v);
11965                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11966                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11967                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11968                 c2[3] = c[3];
11969         }
11970         rsurface.passcolor4f = rsurface.array_passcolor4f;
11971         rsurface.passcolor4f_vertexbuffer = 0;
11972         rsurface.passcolor4f_bufferoffset = 0;
11973 }
11974
11975 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11976 {
11977         int i;
11978         const float *c;
11979         float *c2;
11980         if (!rsurface.passcolor4f)
11981                 return;
11982         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11983         {
11984                 c2[0] = c[0] * r;
11985                 c2[1] = c[1] * g;
11986                 c2[2] = c[2] * b;
11987                 c2[3] = c[3] * a;
11988         }
11989         rsurface.passcolor4f = rsurface.array_passcolor4f;
11990         rsurface.passcolor4f_vertexbuffer = 0;
11991         rsurface.passcolor4f_bufferoffset = 0;
11992 }
11993
11994 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11995 {
11996         int i;
11997         const float *c;
11998         float *c2;
11999         if (!rsurface.passcolor4f)
12000                 return;
12001         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12002         {
12003                 c2[0] = c[0] + r_refdef.scene.ambient;
12004                 c2[1] = c[1] + r_refdef.scene.ambient;
12005                 c2[2] = c[2] + r_refdef.scene.ambient;
12006                 c2[3] = c[3];
12007         }
12008         rsurface.passcolor4f = rsurface.array_passcolor4f;
12009         rsurface.passcolor4f_vertexbuffer = 0;
12010         rsurface.passcolor4f_bufferoffset = 0;
12011 }
12012
12013 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12014 {
12015         // TODO: optimize
12016         rsurface.passcolor4f = NULL;
12017         rsurface.passcolor4f_vertexbuffer = 0;
12018         rsurface.passcolor4f_bufferoffset = 0;
12019         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12020         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12021         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12022         GL_Color(r, g, b, a);
12023         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12024         RSurf_DrawBatch();
12025 }
12026
12027 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12028 {
12029         // TODO: optimize applyfog && applycolor case
12030         // just apply fog if necessary, and tint the fog color array if necessary
12031         rsurface.passcolor4f = NULL;
12032         rsurface.passcolor4f_vertexbuffer = 0;
12033         rsurface.passcolor4f_bufferoffset = 0;
12034         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12035         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12036         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12037         GL_Color(r, g, b, a);
12038         RSurf_DrawBatch();
12039 }
12040
12041 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12042 {
12043         // TODO: optimize
12044         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12045         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12046         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12047         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12048         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12049         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12050         GL_Color(r, g, b, a);
12051         RSurf_DrawBatch();
12052 }
12053
12054 static void RSurf_DrawBatch_GL11_ClampColor(void)
12055 {
12056         int i;
12057         const float *c1;
12058         float *c2;
12059         if (!rsurface.passcolor4f)
12060                 return;
12061         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12062         {
12063                 c2[0] = bound(0.0f, c1[0], 1.0f);
12064                 c2[1] = bound(0.0f, c1[1], 1.0f);
12065                 c2[2] = bound(0.0f, c1[2], 1.0f);
12066                 c2[3] = bound(0.0f, c1[3], 1.0f);
12067         }
12068 }
12069
12070 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12071 {
12072         int i;
12073         float f;
12074         float alpha;
12075         const float *v;
12076         const float *n;
12077         float *c;
12078         vec3_t ambientcolor;
12079         vec3_t diffusecolor;
12080         vec3_t lightdir;
12081         // TODO: optimize
12082         // model lighting
12083         VectorCopy(rsurface.modellight_lightdir, lightdir);
12084         f = 0.5f * r_refdef.lightmapintensity;
12085         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12086         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12087         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12088         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12089         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12090         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12091         alpha = *a;
12092         if (VectorLength2(diffusecolor) > 0)
12093         {
12094                 // q3-style directional shading
12095                 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)
12096                 {
12097                         if ((f = DotProduct(n, lightdir)) > 0)
12098                                 VectorMA(ambientcolor, f, diffusecolor, c);
12099                         else
12100                                 VectorCopy(ambientcolor, c);
12101                         c[3] = alpha;
12102                 }
12103                 *r = 1;
12104                 *g = 1;
12105                 *b = 1;
12106                 *a = 1;
12107                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12108                 rsurface.passcolor4f_vertexbuffer = 0;
12109                 rsurface.passcolor4f_bufferoffset = 0;
12110                 *applycolor = false;
12111         }
12112         else
12113         {
12114                 *r = ambientcolor[0];
12115                 *g = ambientcolor[1];
12116                 *b = ambientcolor[2];
12117                 rsurface.passcolor4f = NULL;
12118                 rsurface.passcolor4f_vertexbuffer = 0;
12119                 rsurface.passcolor4f_bufferoffset = 0;
12120         }
12121 }
12122
12123 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12124 {
12125         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12126         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12127         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12128         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12129         GL_Color(r, g, b, a);
12130         RSurf_DrawBatch();
12131 }
12132
12133 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12134 {
12135         int i;
12136         float f;
12137         const float *v;
12138         float *c;
12139         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12140         {
12141                 f = 1 - RSurf_FogVertex(v);
12142                 c[0] = r;
12143                 c[1] = g;
12144                 c[2] = b;
12145                 c[3] = f * a;
12146         }
12147 }
12148
12149 void RSurf_SetupDepthAndCulling(void)
12150 {
12151         // submodels are biased to avoid z-fighting with world surfaces that they
12152         // may be exactly overlapping (avoids z-fighting artifacts on certain
12153         // doors and things in Quake maps)
12154         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12155         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12156         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12157         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12158 }
12159
12160 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12161 {
12162         // transparent sky would be ridiculous
12163         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12164                 return;
12165         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12166         skyrenderlater = true;
12167         RSurf_SetupDepthAndCulling();
12168         GL_DepthMask(true);
12169         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12170         // skymasking on them, and Quake3 never did sky masking (unlike
12171         // software Quake and software Quake2), so disable the sky masking
12172         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12173         // and skymasking also looks very bad when noclipping outside the
12174         // level, so don't use it then either.
12175         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12176         {
12177                 R_Mesh_ResetTextureState();
12178                 if (skyrendermasked)
12179                 {
12180                         R_SetupShader_DepthOrShadow();
12181                         // depth-only (masking)
12182                         GL_ColorMask(0,0,0,0);
12183                         // just to make sure that braindead drivers don't draw
12184                         // anything despite that colormask...
12185                         GL_BlendFunc(GL_ZERO, GL_ONE);
12186                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12187                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12188                 }
12189                 else
12190                 {
12191                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12192                         // fog sky
12193                         GL_BlendFunc(GL_ONE, GL_ZERO);
12194                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12195                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12196                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12197                 }
12198                 RSurf_DrawBatch();
12199                 if (skyrendermasked)
12200                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12201         }
12202         R_Mesh_ResetTextureState();
12203         GL_Color(1, 1, 1, 1);
12204 }
12205
12206 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12207 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12208 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12209 {
12210         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12211                 return;
12212         if (prepass)
12213         {
12214                 // render screenspace normalmap to texture
12215                 GL_DepthMask(true);
12216                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12217                 RSurf_DrawBatch();
12218                 return;
12219         }
12220
12221         // bind lightmap texture
12222
12223         // water/refraction/reflection/camera surfaces have to be handled specially
12224         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12225         {
12226                 int start, end, startplaneindex;
12227                 for (start = 0;start < texturenumsurfaces;start = end)
12228                 {
12229                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12230                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12231                                 ;
12232                         // now that we have a batch using the same planeindex, render it
12233                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12234                         {
12235                                 // render water or distortion background
12236                                 GL_DepthMask(true);
12237                                 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));
12238                                 RSurf_DrawBatch();
12239                                 // blend surface on top
12240                                 GL_DepthMask(false);
12241                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12242                                 RSurf_DrawBatch();
12243                         }
12244                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12245                         {
12246                                 // render surface with reflection texture as input
12247                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12248                                 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));
12249                                 RSurf_DrawBatch();
12250                         }
12251                 }
12252                 return;
12253         }
12254
12255         // render surface batch normally
12256         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12257         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12258         RSurf_DrawBatch();
12259 }
12260
12261 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12262 {
12263         // OpenGL 1.3 path - anything not completely ancient
12264         qboolean applycolor;
12265         qboolean applyfog;
12266         int layerindex;
12267         const texturelayer_t *layer;
12268         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);
12269         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12270
12271         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12272         {
12273                 vec4_t layercolor;
12274                 int layertexrgbscale;
12275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12276                 {
12277                         if (layerindex == 0)
12278                                 GL_AlphaTest(true);
12279                         else
12280                         {
12281                                 GL_AlphaTest(false);
12282                                 GL_DepthFunc(GL_EQUAL);
12283                         }
12284                 }
12285                 GL_DepthMask(layer->depthmask && writedepth);
12286                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12287                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12288                 {
12289                         layertexrgbscale = 4;
12290                         VectorScale(layer->color, 0.25f, layercolor);
12291                 }
12292                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12293                 {
12294                         layertexrgbscale = 2;
12295                         VectorScale(layer->color, 0.5f, layercolor);
12296                 }
12297                 else
12298                 {
12299                         layertexrgbscale = 1;
12300                         VectorScale(layer->color, 1.0f, layercolor);
12301                 }
12302                 layercolor[3] = layer->color[3];
12303                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12304                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12305                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12306                 switch (layer->type)
12307                 {
12308                 case TEXTURELAYERTYPE_LITTEXTURE:
12309                         // single-pass lightmapped texture with 2x rgbscale
12310                         R_Mesh_TexBind(0, r_texture_white);
12311                         R_Mesh_TexMatrix(0, NULL);
12312                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12313                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12314                         R_Mesh_TexBind(1, layer->texture);
12315                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12316                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12317                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12318                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12319                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12320                         else if (rsurface.uselightmaptexture)
12321                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12322                         else
12323                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12324                         break;
12325                 case TEXTURELAYERTYPE_TEXTURE:
12326                         // singletexture unlit texture with transparency support
12327                         R_Mesh_TexBind(0, layer->texture);
12328                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12329                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12330                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12331                         R_Mesh_TexBind(1, 0);
12332                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12333                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12334                         break;
12335                 case TEXTURELAYERTYPE_FOG:
12336                         // singletexture fogging
12337                         if (layer->texture)
12338                         {
12339                                 R_Mesh_TexBind(0, layer->texture);
12340                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12341                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12342                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12343                         }
12344                         else
12345                         {
12346                                 R_Mesh_TexBind(0, 0);
12347                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12348                         }
12349                         R_Mesh_TexBind(1, 0);
12350                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12351                         // generate a color array for the fog pass
12352                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12353                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12354                         RSurf_DrawBatch();
12355                         break;
12356                 default:
12357                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12358                 }
12359         }
12360         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12361         {
12362                 GL_DepthFunc(GL_LEQUAL);
12363                 GL_AlphaTest(false);
12364         }
12365 }
12366
12367 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12368 {
12369         // OpenGL 1.1 - crusty old voodoo path
12370         qboolean applyfog;
12371         int layerindex;
12372         const texturelayer_t *layer;
12373         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);
12374         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12375
12376         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12377         {
12378                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12379                 {
12380                         if (layerindex == 0)
12381                                 GL_AlphaTest(true);
12382                         else
12383                         {
12384                                 GL_AlphaTest(false);
12385                                 GL_DepthFunc(GL_EQUAL);
12386                         }
12387                 }
12388                 GL_DepthMask(layer->depthmask && writedepth);
12389                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12390                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12391                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12392                 switch (layer->type)
12393                 {
12394                 case TEXTURELAYERTYPE_LITTEXTURE:
12395                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12396                         {
12397                                 // two-pass lit texture with 2x rgbscale
12398                                 // first the lightmap pass
12399                                 R_Mesh_TexBind(0, r_texture_white);
12400                                 R_Mesh_TexMatrix(0, NULL);
12401                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12402                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12403                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12404                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12405                                 else if (rsurface.uselightmaptexture)
12406                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12407                                 else
12408                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12409                                 // then apply the texture to it
12410                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12411                                 R_Mesh_TexBind(0, layer->texture);
12412                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12413                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12414                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12415                                 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);
12416                         }
12417                         else
12418                         {
12419                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12420                                 R_Mesh_TexBind(0, layer->texture);
12421                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12422                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12423                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12424                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12425                                         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);
12426                                 else
12427                                         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);
12428                         }
12429                         break;
12430                 case TEXTURELAYERTYPE_TEXTURE:
12431                         // singletexture unlit texture with transparency support
12432                         R_Mesh_TexBind(0, layer->texture);
12433                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12434                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12435                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12436                         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);
12437                         break;
12438                 case TEXTURELAYERTYPE_FOG:
12439                         // singletexture fogging
12440                         if (layer->texture)
12441                         {
12442                                 R_Mesh_TexBind(0, layer->texture);
12443                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12444                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12445                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12446                         }
12447                         else
12448                         {
12449                                 R_Mesh_TexBind(0, 0);
12450                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12451                         }
12452                         // generate a color array for the fog pass
12453                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12454                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12455                         RSurf_DrawBatch();
12456                         break;
12457                 default:
12458                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12459                 }
12460         }
12461         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12462         {
12463                 GL_DepthFunc(GL_LEQUAL);
12464                 GL_AlphaTest(false);
12465         }
12466 }
12467
12468 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12469 {
12470         int vi;
12471         int j;
12472         r_vertexgeneric_t *batchvertex;
12473         float c[4];
12474
12475         GL_AlphaTest(false);
12476         R_Mesh_ResetTextureState();
12477         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12478
12479         if(rsurface.texture && rsurface.texture->currentskinframe)
12480         {
12481                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12482                 c[3] *= rsurface.texture->currentalpha;
12483         }
12484         else
12485         {
12486                 c[0] = 1;
12487                 c[1] = 0;
12488                 c[2] = 1;
12489                 c[3] = 1;
12490         }
12491
12492         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12493         {
12494                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12495                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12496                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12497         }
12498
12499         // brighten it up (as texture value 127 means "unlit")
12500         c[0] *= 2 * r_refdef.view.colorscale;
12501         c[1] *= 2 * r_refdef.view.colorscale;
12502         c[2] *= 2 * r_refdef.view.colorscale;
12503
12504         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12505                 c[3] *= r_wateralpha.value;
12506
12507         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12508         {
12509                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12510                 GL_DepthMask(false);
12511         }
12512         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12513         {
12514                 GL_BlendFunc(GL_ONE, GL_ONE);
12515                 GL_DepthMask(false);
12516         }
12517         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12518         {
12519                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12520                 GL_DepthMask(false);
12521         }
12522         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12523         {
12524                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12525                 GL_DepthMask(false);
12526         }
12527         else
12528         {
12529                 GL_BlendFunc(GL_ONE, GL_ZERO);
12530                 GL_DepthMask(writedepth);
12531         }
12532
12533         if (r_showsurfaces.integer == 3)
12534         {
12535                 rsurface.passcolor4f = NULL;
12536
12537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12538                 {
12539                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12540
12541                         rsurface.passcolor4f = NULL;
12542                         rsurface.passcolor4f_vertexbuffer = 0;
12543                         rsurface.passcolor4f_bufferoffset = 0;
12544                 }
12545                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12546                 {
12547                         qboolean applycolor = true;
12548                         float one = 1.0;
12549
12550                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12551
12552                         r_refdef.lightmapintensity = 1;
12553                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12554                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12555                 }
12556                 else
12557                 {
12558                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12559
12560                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12561                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12562                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12563                 }
12564
12565                 if(!rsurface.passcolor4f)
12566                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12567
12568                 RSurf_DrawBatch_GL11_ApplyAmbient();
12569                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12570                 if(r_refdef.fogenabled)
12571                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12572                 RSurf_DrawBatch_GL11_ClampColor();
12573
12574                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12575                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12576                 RSurf_DrawBatch();
12577         }
12578         else if (!r_refdef.view.showdebug)
12579         {
12580                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12581                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12582                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12583                 {
12584                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12585                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12586                 }
12587                 R_Mesh_PrepareVertices_Generic_Unlock();
12588                 RSurf_DrawBatch();
12589         }
12590         else if (r_showsurfaces.integer == 4)
12591         {
12592                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12593                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12594                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12595                 {
12596                         unsigned char c = vi << 3;
12597                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12598                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12599                 }
12600                 R_Mesh_PrepareVertices_Generic_Unlock();
12601                 RSurf_DrawBatch();
12602         }
12603         else if (r_showsurfaces.integer == 2)
12604         {
12605                 const int *e;
12606                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12607                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12608                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12609                 {
12610                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12611                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12612                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12613                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12614                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12615                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12616                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12617                 }
12618                 R_Mesh_PrepareVertices_Generic_Unlock();
12619                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12620         }
12621         else
12622         {
12623                 int texturesurfaceindex;
12624                 int k;
12625                 const msurface_t *surface;
12626                 unsigned char surfacecolor4ub[4];
12627                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12628                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12629                 vi = 0;
12630                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12631                 {
12632                         surface = texturesurfacelist[texturesurfaceindex];
12633                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12634                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12635                         for (j = 0;j < surface->num_vertices;j++)
12636                         {
12637                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12638                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12639                                 vi++;
12640                         }
12641                 }
12642                 R_Mesh_PrepareVertices_Generic_Unlock();
12643                 RSurf_DrawBatch();
12644         }
12645 }
12646
12647 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12648 {
12649         CHECKGLERROR
12650         RSurf_SetupDepthAndCulling();
12651         if (r_showsurfaces.integer)
12652         {
12653                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12654                 return;
12655         }
12656         switch (vid.renderpath)
12657         {
12658         case RENDERPATH_GL20:
12659         case RENDERPATH_CGGL:
12660         case RENDERPATH_D3D9:
12661         case RENDERPATH_D3D10:
12662         case RENDERPATH_D3D11:
12663                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12664                 break;
12665         case RENDERPATH_GL13:
12666                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12667                 break;
12668         case RENDERPATH_GL11:
12669                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12670                 break;
12671         }
12672         CHECKGLERROR
12673 }
12674
12675 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12676 {
12677         CHECKGLERROR
12678         RSurf_SetupDepthAndCulling();
12679         if (r_showsurfaces.integer)
12680         {
12681                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12682                 return;
12683         }
12684         switch (vid.renderpath)
12685         {
12686         case RENDERPATH_GL20:
12687         case RENDERPATH_CGGL:
12688         case RENDERPATH_D3D9:
12689         case RENDERPATH_D3D10:
12690         case RENDERPATH_D3D11:
12691                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12692                 break;
12693         case RENDERPATH_GL13:
12694                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12695                 break;
12696         case RENDERPATH_GL11:
12697                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12698                 break;
12699         }
12700         CHECKGLERROR
12701 }
12702
12703 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12704 {
12705         int i, j;
12706         int texturenumsurfaces, endsurface;
12707         texture_t *texture;
12708         const msurface_t *surface;
12709 #define MAXBATCH_TRANSPARENTSURFACES 256
12710         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12711
12712         // if the model is static it doesn't matter what value we give for
12713         // wantnormals and wanttangents, so this logic uses only rules applicable
12714         // to a model, knowing that they are meaningless otherwise
12715         if (ent == r_refdef.scene.worldentity)
12716                 RSurf_ActiveWorldEntity();
12717         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12718                 RSurf_ActiveModelEntity(ent, false, false, false);
12719         else
12720         {
12721                 switch (vid.renderpath)
12722                 {
12723                 case RENDERPATH_GL20:
12724                 case RENDERPATH_CGGL:
12725                 case RENDERPATH_D3D9:
12726                 case RENDERPATH_D3D10:
12727                 case RENDERPATH_D3D11:
12728                         RSurf_ActiveModelEntity(ent, true, true, false);
12729                         break;
12730                 case RENDERPATH_GL13:
12731                 case RENDERPATH_GL11:
12732                         RSurf_ActiveModelEntity(ent, true, false, false);
12733                         break;
12734                 }
12735         }
12736
12737         if (r_transparentdepthmasking.integer)
12738         {
12739                 qboolean setup = false;
12740                 for (i = 0;i < numsurfaces;i = j)
12741                 {
12742                         j = i + 1;
12743                         surface = rsurface.modelsurfaces + surfacelist[i];
12744                         texture = surface->texture;
12745                         rsurface.texture = R_GetCurrentTexture(texture);
12746                         rsurface.lightmaptexture = NULL;
12747                         rsurface.deluxemaptexture = NULL;
12748                         rsurface.uselightmaptexture = false;
12749                         // scan ahead until we find a different texture
12750                         endsurface = min(i + 1024, numsurfaces);
12751                         texturenumsurfaces = 0;
12752                         texturesurfacelist[texturenumsurfaces++] = surface;
12753                         for (;j < endsurface;j++)
12754                         {
12755                                 surface = rsurface.modelsurfaces + surfacelist[j];
12756                                 if (texture != surface->texture)
12757                                         break;
12758                                 texturesurfacelist[texturenumsurfaces++] = surface;
12759                         }
12760                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12761                                 continue;
12762                         // render the range of surfaces as depth
12763                         if (!setup)
12764                         {
12765                                 setup = true;
12766                                 GL_ColorMask(0,0,0,0);
12767                                 GL_Color(1,1,1,1);
12768                                 GL_DepthTest(true);
12769                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12770                                 GL_DepthMask(true);
12771                                 GL_AlphaTest(false);
12772                                 R_Mesh_ResetTextureState();
12773                                 R_SetupShader_DepthOrShadow();
12774                         }
12775                         RSurf_SetupDepthAndCulling();
12776                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12777                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12778                         RSurf_DrawBatch();
12779                 }
12780                 if (setup)
12781                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12782         }
12783
12784         for (i = 0;i < numsurfaces;i = j)
12785         {
12786                 j = i + 1;
12787                 surface = rsurface.modelsurfaces + surfacelist[i];
12788                 texture = surface->texture;
12789                 rsurface.texture = R_GetCurrentTexture(texture);
12790                 rsurface.lightmaptexture = surface->lightmaptexture;
12791                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12792                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12793                 // scan ahead until we find a different texture
12794                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12795                 texturenumsurfaces = 0;
12796                 texturesurfacelist[texturenumsurfaces++] = surface;
12797                 for (;j < endsurface;j++)
12798                 {
12799                         surface = rsurface.modelsurfaces + surfacelist[j];
12800                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12801                                 break;
12802                         texturesurfacelist[texturenumsurfaces++] = surface;
12803                 }
12804                 // render the range of surfaces
12805                 if (ent == r_refdef.scene.worldentity)
12806                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12807                 else
12808                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12809         }
12810         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12811         GL_AlphaTest(false);
12812 }
12813
12814 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12815 {
12816         // transparent surfaces get pushed off into the transparent queue
12817         int surfacelistindex;
12818         const msurface_t *surface;
12819         vec3_t tempcenter, center;
12820         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12821         {
12822                 surface = texturesurfacelist[surfacelistindex];
12823                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12824                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12825                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12826                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12827                 if (queueentity->transparent_offset) // transparent offset
12828                 {
12829                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12830                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12831                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12832                 }
12833                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12834         }
12835 }
12836
12837 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12838 {
12839         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12840                 return;
12841         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12842                 return;
12843         RSurf_SetupDepthAndCulling();
12844         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12845         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12846         RSurf_DrawBatch();
12847 }
12848
12849 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12850 {
12851         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12852         CHECKGLERROR
12853         if (depthonly)
12854                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12855         else if (prepass)
12856         {
12857                 if (!rsurface.texture->currentnumlayers)
12858                         return;
12859                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12860                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12861                 else
12862                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12863         }
12864         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12865                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12866         else if (!rsurface.texture->currentnumlayers)
12867                 return;
12868         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12869         {
12870                 // in the deferred case, transparent surfaces were queued during prepass
12871                 if (!r_shadow_usingdeferredprepass)
12872                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12873         }
12874         else
12875         {
12876                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12877                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12878         }
12879         CHECKGLERROR
12880 }
12881
12882 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12883 {
12884         int i, j;
12885         texture_t *texture;
12886         // break the surface list down into batches by texture and use of lightmapping
12887         for (i = 0;i < numsurfaces;i = j)
12888         {
12889                 j = i + 1;
12890                 // texture is the base texture pointer, rsurface.texture is the
12891                 // current frame/skin the texture is directing us to use (for example
12892                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12893                 // use skin 1 instead)
12894                 texture = surfacelist[i]->texture;
12895                 rsurface.texture = R_GetCurrentTexture(texture);
12896                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12897                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12898                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12899                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12900                 {
12901                         // if this texture is not the kind we want, skip ahead to the next one
12902                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12903                                 ;
12904                         continue;
12905                 }
12906                 // simply scan ahead until we find a different texture or lightmap state
12907                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12908                         ;
12909                 // render the range of surfaces
12910                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12911         }
12912 }
12913
12914 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12915 {
12916         CHECKGLERROR
12917         if (depthonly)
12918                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12919         else if (prepass)
12920         {
12921                 if (!rsurface.texture->currentnumlayers)
12922                         return;
12923                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12924                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12925                 else
12926                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12927         }
12928         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12929                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12930         else if (!rsurface.texture->currentnumlayers)
12931                 return;
12932         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12933         {
12934                 // in the deferred case, transparent surfaces were queued during prepass
12935                 if (!r_shadow_usingdeferredprepass)
12936                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12937         }
12938         else
12939         {
12940                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12941                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12942         }
12943         CHECKGLERROR
12944 }
12945
12946 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12947 {
12948         int i, j;
12949         texture_t *texture;
12950         // break the surface list down into batches by texture and use of lightmapping
12951         for (i = 0;i < numsurfaces;i = j)
12952         {
12953                 j = i + 1;
12954                 // texture is the base texture pointer, rsurface.texture is the
12955                 // current frame/skin the texture is directing us to use (for example
12956                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12957                 // use skin 1 instead)
12958                 texture = surfacelist[i]->texture;
12959                 rsurface.texture = R_GetCurrentTexture(texture);
12960                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12961                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12962                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12963                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12964                 {
12965                         // if this texture is not the kind we want, skip ahead to the next one
12966                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12967                                 ;
12968                         continue;
12969                 }
12970                 // simply scan ahead until we find a different texture or lightmap state
12971                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12972                         ;
12973                 // render the range of surfaces
12974                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12975         }
12976 }
12977
12978 float locboxvertex3f[6*4*3] =
12979 {
12980         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12981         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12982         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12983         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12984         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12985         1,0,0, 0,0,0, 0,1,0, 1,1,0
12986 };
12987
12988 unsigned short locboxelements[6*2*3] =
12989 {
12990          0, 1, 2, 0, 2, 3,
12991          4, 5, 6, 4, 6, 7,
12992          8, 9,10, 8,10,11,
12993         12,13,14, 12,14,15,
12994         16,17,18, 16,18,19,
12995         20,21,22, 20,22,23
12996 };
12997
12998 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12999 {
13000         int i, j;
13001         cl_locnode_t *loc = (cl_locnode_t *)ent;
13002         vec3_t mins, size;
13003         float vertex3f[6*4*3];
13004         CHECKGLERROR
13005         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13006         GL_DepthMask(false);
13007         GL_DepthRange(0, 1);
13008         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13009         GL_DepthTest(true);
13010         GL_CullFace(GL_NONE);
13011         R_EntityMatrix(&identitymatrix);
13012
13013         R_Mesh_ResetTextureState();
13014
13015         i = surfacelist[0];
13016         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13017                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13018                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13019                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13020
13021         if (VectorCompare(loc->mins, loc->maxs))
13022         {
13023                 VectorSet(size, 2, 2, 2);
13024                 VectorMA(loc->mins, -0.5f, size, mins);
13025         }
13026         else
13027         {
13028                 VectorCopy(loc->mins, mins);
13029                 VectorSubtract(loc->maxs, loc->mins, size);
13030         }
13031
13032         for (i = 0;i < 6*4*3;)
13033                 for (j = 0;j < 3;j++, i++)
13034                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13035
13036         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13037         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13038         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13039 }
13040
13041 void R_DrawLocs(void)
13042 {
13043         int index;
13044         cl_locnode_t *loc, *nearestloc;
13045         vec3_t center;
13046         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13047         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13048         {
13049                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13050                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13051         }
13052 }
13053
13054 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13055 {
13056         if (decalsystem->decals)
13057                 Mem_Free(decalsystem->decals);
13058         memset(decalsystem, 0, sizeof(*decalsystem));
13059 }
13060
13061 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)
13062 {
13063         tridecal_t *decal;
13064         tridecal_t *decals;
13065         int i;
13066
13067         // expand or initialize the system
13068         if (decalsystem->maxdecals <= decalsystem->numdecals)
13069         {
13070                 decalsystem_t old = *decalsystem;
13071                 qboolean useshortelements;
13072                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13073                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13074                 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)));
13075                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13076                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13077                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13078                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13079                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13080                 if (decalsystem->numdecals)
13081                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13082                 if (old.decals)
13083                         Mem_Free(old.decals);
13084                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13085                         decalsystem->element3i[i] = i;
13086                 if (useshortelements)
13087                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13088                                 decalsystem->element3s[i] = i;
13089         }
13090
13091         // grab a decal and search for another free slot for the next one
13092         decals = decalsystem->decals;
13093         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13094         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13095                 ;
13096         decalsystem->freedecal = i;
13097         if (decalsystem->numdecals <= i)
13098                 decalsystem->numdecals = i + 1;
13099
13100         // initialize the decal
13101         decal->lived = 0;
13102         decal->triangleindex = triangleindex;
13103         decal->surfaceindex = surfaceindex;
13104         decal->decalsequence = decalsequence;
13105         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13106         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13107         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13108         decal->color4ub[0][3] = 255;
13109         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13110         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13111         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13112         decal->color4ub[1][3] = 255;
13113         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13114         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13115         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13116         decal->color4ub[2][3] = 255;
13117         decal->vertex3f[0][0] = v0[0];
13118         decal->vertex3f[0][1] = v0[1];
13119         decal->vertex3f[0][2] = v0[2];
13120         decal->vertex3f[1][0] = v1[0];
13121         decal->vertex3f[1][1] = v1[1];
13122         decal->vertex3f[1][2] = v1[2];
13123         decal->vertex3f[2][0] = v2[0];
13124         decal->vertex3f[2][1] = v2[1];
13125         decal->vertex3f[2][2] = v2[2];
13126         decal->texcoord2f[0][0] = t0[0];
13127         decal->texcoord2f[0][1] = t0[1];
13128         decal->texcoord2f[1][0] = t1[0];
13129         decal->texcoord2f[1][1] = t1[1];
13130         decal->texcoord2f[2][0] = t2[0];
13131         decal->texcoord2f[2][1] = t2[1];
13132 }
13133
13134 extern cvar_t cl_decals_bias;
13135 extern cvar_t cl_decals_models;
13136 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13137 // baseparms, parms, temps
13138 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)
13139 {
13140         int cornerindex;
13141         int index;
13142         float v[9][3];
13143         const float *vertex3f;
13144         int numpoints;
13145         float points[2][9][3];
13146         float temp[3];
13147         float tc[9][2];
13148         float f;
13149         float c[9][4];
13150         const int *e;
13151
13152         e = rsurface.modelelement3i + 3*triangleindex;
13153
13154         vertex3f = rsurface.modelvertex3f;
13155
13156         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13157         {
13158                 index = 3*e[cornerindex];
13159                 VectorCopy(vertex3f + index, v[cornerindex]);
13160         }
13161         // cull backfaces
13162         //TriangleNormal(v[0], v[1], v[2], normal);
13163         //if (DotProduct(normal, localnormal) < 0.0f)
13164         //      continue;
13165         // clip by each of the box planes formed from the projection matrix
13166         // if anything survives, we emit the decal
13167         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]);
13168         if (numpoints < 3)
13169                 return;
13170         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]);
13171         if (numpoints < 3)
13172                 return;
13173         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]);
13174         if (numpoints < 3)
13175                 return;
13176         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]);
13177         if (numpoints < 3)
13178                 return;
13179         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]);
13180         if (numpoints < 3)
13181                 return;
13182         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]);
13183         if (numpoints < 3)
13184                 return;
13185         // some part of the triangle survived, so we have to accept it...
13186         if (dynamic)
13187         {
13188                 // dynamic always uses the original triangle
13189                 numpoints = 3;
13190                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13191                 {
13192                         index = 3*e[cornerindex];
13193                         VectorCopy(vertex3f + index, v[cornerindex]);
13194                 }
13195         }
13196         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13197         {
13198                 // convert vertex positions to texcoords
13199                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13200                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13201                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13202                 // calculate distance fade from the projection origin
13203                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13204                 f = bound(0.0f, f, 1.0f);
13205                 c[cornerindex][0] = r * f;
13206                 c[cornerindex][1] = g * f;
13207                 c[cornerindex][2] = b * f;
13208                 c[cornerindex][3] = 1.0f;
13209                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13210         }
13211         if (dynamic)
13212                 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);
13213         else
13214                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13215                         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);
13216 }
13217 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)
13218 {
13219         matrix4x4_t projection;
13220         decalsystem_t *decalsystem;
13221         qboolean dynamic;
13222         dp_model_t *model;
13223         const msurface_t *surface;
13224         const msurface_t *surfaces;
13225         const int *surfacelist;
13226         const texture_t *texture;
13227         int numtriangles;
13228         int numsurfacelist;
13229         int surfacelistindex;
13230         int surfaceindex;
13231         int triangleindex;
13232         float localorigin[3];
13233         float localnormal[3];
13234         float localmins[3];
13235         float localmaxs[3];
13236         float localsize;
13237         //float normal[3];
13238         float planes[6][4];
13239         float angles[3];
13240         bih_t *bih;
13241         int bih_triangles_count;
13242         int bih_triangles[256];
13243         int bih_surfaces[256];
13244
13245         decalsystem = &ent->decalsystem;
13246         model = ent->model;
13247         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13248         {
13249                 R_DecalSystem_Reset(&ent->decalsystem);
13250                 return;
13251         }
13252
13253         if (!model->brush.data_leafs && !cl_decals_models.integer)
13254         {
13255                 if (decalsystem->model)
13256                         R_DecalSystem_Reset(decalsystem);
13257                 return;
13258         }
13259
13260         if (decalsystem->model != model)
13261                 R_DecalSystem_Reset(decalsystem);
13262         decalsystem->model = model;
13263
13264         RSurf_ActiveModelEntity(ent, false, false, false);
13265
13266         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13267         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13268         VectorNormalize(localnormal);
13269         localsize = worldsize*rsurface.inversematrixscale;
13270         localmins[0] = localorigin[0] - localsize;
13271         localmins[1] = localorigin[1] - localsize;
13272         localmins[2] = localorigin[2] - localsize;
13273         localmaxs[0] = localorigin[0] + localsize;
13274         localmaxs[1] = localorigin[1] + localsize;
13275         localmaxs[2] = localorigin[2] + localsize;
13276
13277         //VectorCopy(localnormal, planes[4]);
13278         //VectorVectors(planes[4], planes[2], planes[0]);
13279         AnglesFromVectors(angles, localnormal, NULL, false);
13280         AngleVectors(angles, planes[0], planes[2], planes[4]);
13281         VectorNegate(planes[0], planes[1]);
13282         VectorNegate(planes[2], planes[3]);
13283         VectorNegate(planes[4], planes[5]);
13284         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13285         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13286         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13287         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13288         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13289         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13290
13291 #if 1
13292 // works
13293 {
13294         matrix4x4_t forwardprojection;
13295         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13296         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13297 }
13298 #else
13299 // broken
13300 {
13301         float projectionvector[4][3];
13302         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13303         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13304         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13305         projectionvector[0][0] = planes[0][0] * ilocalsize;
13306         projectionvector[0][1] = planes[1][0] * ilocalsize;
13307         projectionvector[0][2] = planes[2][0] * ilocalsize;
13308         projectionvector[1][0] = planes[0][1] * ilocalsize;
13309         projectionvector[1][1] = planes[1][1] * ilocalsize;
13310         projectionvector[1][2] = planes[2][1] * ilocalsize;
13311         projectionvector[2][0] = planes[0][2] * ilocalsize;
13312         projectionvector[2][1] = planes[1][2] * ilocalsize;
13313         projectionvector[2][2] = planes[2][2] * ilocalsize;
13314         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13315         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13316         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13317         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13318 }
13319 #endif
13320
13321         dynamic = model->surfmesh.isanimated;
13322         numsurfacelist = model->nummodelsurfaces;
13323         surfacelist = model->sortedmodelsurfaces;
13324         surfaces = model->data_surfaces;
13325
13326         bih = NULL;
13327         bih_triangles_count = -1;
13328         if(!dynamic)
13329         {
13330                 if(model->render_bih.numleafs)
13331                         bih = &model->render_bih;
13332                 else if(model->collision_bih.numleafs)
13333                         bih = &model->collision_bih;
13334         }
13335         if(bih)
13336                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13337         if(bih_triangles_count == 0)
13338                 return;
13339         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13340                 return;
13341         if(bih_triangles_count > 0)
13342         {
13343                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13344                 {
13345                         surfaceindex = bih_surfaces[triangleindex];
13346                         surface = surfaces + surfaceindex;
13347                         texture = surface->texture;
13348                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13349                                 continue;
13350                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13351                                 continue;
13352                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13353                 }
13354         }
13355         else
13356         {
13357                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13358                 {
13359                         surfaceindex = surfacelist[surfacelistindex];
13360                         surface = surfaces + surfaceindex;
13361                         // check cull box first because it rejects more than any other check
13362                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13363                                 continue;
13364                         // skip transparent surfaces
13365                         texture = surface->texture;
13366                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13367                                 continue;
13368                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13369                                 continue;
13370                         numtriangles = surface->num_triangles;
13371                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13372                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13373                 }
13374         }
13375 }
13376
13377 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13378 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)
13379 {
13380         int renderentityindex;
13381         float worldmins[3];
13382         float worldmaxs[3];
13383         entity_render_t *ent;
13384
13385         if (!cl_decals_newsystem.integer)
13386                 return;
13387
13388         worldmins[0] = worldorigin[0] - worldsize;
13389         worldmins[1] = worldorigin[1] - worldsize;
13390         worldmins[2] = worldorigin[2] - worldsize;
13391         worldmaxs[0] = worldorigin[0] + worldsize;
13392         worldmaxs[1] = worldorigin[1] + worldsize;
13393         worldmaxs[2] = worldorigin[2] + worldsize;
13394
13395         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13396
13397         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13398         {
13399                 ent = r_refdef.scene.entities[renderentityindex];
13400                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13401                         continue;
13402
13403                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13404         }
13405 }
13406
13407 typedef struct r_decalsystem_splatqueue_s
13408 {
13409         vec3_t worldorigin;
13410         vec3_t worldnormal;
13411         float color[4];
13412         float tcrange[4];
13413         float worldsize;
13414         int decalsequence;
13415 }
13416 r_decalsystem_splatqueue_t;
13417
13418 int r_decalsystem_numqueued = 0;
13419 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13420
13421 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)
13422 {
13423         r_decalsystem_splatqueue_t *queue;
13424
13425         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13426                 return;
13427
13428         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13429         VectorCopy(worldorigin, queue->worldorigin);
13430         VectorCopy(worldnormal, queue->worldnormal);
13431         Vector4Set(queue->color, r, g, b, a);
13432         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13433         queue->worldsize = worldsize;
13434         queue->decalsequence = cl.decalsequence++;
13435 }
13436
13437 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13438 {
13439         int i;
13440         r_decalsystem_splatqueue_t *queue;
13441
13442         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13443                 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);
13444         r_decalsystem_numqueued = 0;
13445 }
13446
13447 extern cvar_t cl_decals_max;
13448 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13449 {
13450         int i;
13451         decalsystem_t *decalsystem = &ent->decalsystem;
13452         int numdecals;
13453         int killsequence;
13454         tridecal_t *decal;
13455         float frametime;
13456         float lifetime;
13457
13458         if (!decalsystem->numdecals)
13459                 return;
13460
13461         if (r_showsurfaces.integer)
13462                 return;
13463
13464         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13465         {
13466                 R_DecalSystem_Reset(decalsystem);
13467                 return;
13468         }
13469
13470         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13471         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13472
13473         if (decalsystem->lastupdatetime)
13474                 frametime = (cl.time - decalsystem->lastupdatetime);
13475         else
13476                 frametime = 0;
13477         decalsystem->lastupdatetime = cl.time;
13478         decal = decalsystem->decals;
13479         numdecals = decalsystem->numdecals;
13480
13481         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13482         {
13483                 if (decal->color4ub[0][3])
13484                 {
13485                         decal->lived += frametime;
13486                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13487                         {
13488                                 memset(decal, 0, sizeof(*decal));
13489                                 if (decalsystem->freedecal > i)
13490                                         decalsystem->freedecal = i;
13491                         }
13492                 }
13493         }
13494         decal = decalsystem->decals;
13495         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13496                 numdecals--;
13497
13498         // collapse the array by shuffling the tail decals into the gaps
13499         for (;;)
13500         {
13501                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13502                         decalsystem->freedecal++;
13503                 if (decalsystem->freedecal == numdecals)
13504                         break;
13505                 decal[decalsystem->freedecal] = decal[--numdecals];
13506         }
13507
13508         decalsystem->numdecals = numdecals;
13509
13510         if (numdecals <= 0)
13511         {
13512                 // if there are no decals left, reset decalsystem
13513                 R_DecalSystem_Reset(decalsystem);
13514         }
13515 }
13516
13517 extern skinframe_t *decalskinframe;
13518 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13519 {
13520         int i;
13521         decalsystem_t *decalsystem = &ent->decalsystem;
13522         int numdecals;
13523         tridecal_t *decal;
13524         float faderate;
13525         float alpha;
13526         float *v3f;
13527         float *c4f;
13528         float *t2f;
13529         const int *e;
13530         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13531         int numtris = 0;
13532
13533         numdecals = decalsystem->numdecals;
13534         if (!numdecals)
13535                 return;
13536
13537         if (r_showsurfaces.integer)
13538                 return;
13539
13540         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13541         {
13542                 R_DecalSystem_Reset(decalsystem);
13543                 return;
13544         }
13545
13546         // if the model is static it doesn't matter what value we give for
13547         // wantnormals and wanttangents, so this logic uses only rules applicable
13548         // to a model, knowing that they are meaningless otherwise
13549         if (ent == r_refdef.scene.worldentity)
13550                 RSurf_ActiveWorldEntity();
13551         else
13552                 RSurf_ActiveModelEntity(ent, false, false, false);
13553
13554         decalsystem->lastupdatetime = cl.time;
13555         decal = decalsystem->decals;
13556
13557         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13558
13559         // update vertex positions for animated models
13560         v3f = decalsystem->vertex3f;
13561         c4f = decalsystem->color4f;
13562         t2f = decalsystem->texcoord2f;
13563         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13564         {
13565                 if (!decal->color4ub[0][3])
13566                         continue;
13567
13568                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13569                         continue;
13570
13571                 // update color values for fading decals
13572                 if (decal->lived >= cl_decals_time.value)
13573                 {
13574                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13575                         alpha *= (1.0f/255.0f);
13576                 }
13577                 else
13578                         alpha = 1.0f/255.0f;
13579
13580                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13581                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13582                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13583                 c4f[ 3] = 1;
13584                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13585                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13586                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13587                 c4f[ 7] = 1;
13588                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13589                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13590                 c4f[10] = decal->color4ub[2][2] * alpha;
13591                 c4f[11] = 1;
13592
13593                 t2f[0] = decal->texcoord2f[0][0];
13594                 t2f[1] = decal->texcoord2f[0][1];
13595                 t2f[2] = decal->texcoord2f[1][0];
13596                 t2f[3] = decal->texcoord2f[1][1];
13597                 t2f[4] = decal->texcoord2f[2][0];
13598                 t2f[5] = decal->texcoord2f[2][1];
13599
13600                 // update vertex positions for animated models
13601                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13602                 {
13603                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13604                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13605                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13606                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13607                 }
13608                 else
13609                 {
13610                         VectorCopy(decal->vertex3f[0], v3f);
13611                         VectorCopy(decal->vertex3f[1], v3f + 3);
13612                         VectorCopy(decal->vertex3f[2], v3f + 6);
13613                 }
13614
13615                 if (r_refdef.fogenabled)
13616                 {
13617                         alpha = RSurf_FogVertex(v3f);
13618                         VectorScale(c4f, alpha, c4f);
13619                         alpha = RSurf_FogVertex(v3f + 3);
13620                         VectorScale(c4f + 4, alpha, c4f + 4);
13621                         alpha = RSurf_FogVertex(v3f + 6);
13622                         VectorScale(c4f + 8, alpha, c4f + 8);
13623                 }
13624
13625                 v3f += 9;
13626                 c4f += 12;
13627                 t2f += 6;
13628                 numtris++;
13629         }
13630
13631         if (numtris > 0)
13632         {
13633                 r_refdef.stats.drawndecals += numtris;
13634
13635                 // now render the decals all at once
13636                 // (this assumes they all use one particle font texture!)
13637                 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);
13638                 R_Mesh_ResetTextureState();
13639                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13640                 GL_DepthMask(false);
13641                 GL_DepthRange(0, 1);
13642                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13643                 GL_DepthTest(true);
13644                 GL_CullFace(GL_NONE);
13645                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13646                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13647                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13648         }
13649 }
13650
13651 static void R_DrawModelDecals(void)
13652 {
13653         int i, numdecals;
13654
13655         // fade faster when there are too many decals
13656         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13657         for (i = 0;i < r_refdef.scene.numentities;i++)
13658                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13659
13660         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13661         for (i = 0;i < r_refdef.scene.numentities;i++)
13662                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13663                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13664
13665         R_DecalSystem_ApplySplatEntitiesQueue();
13666
13667         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13668         for (i = 0;i < r_refdef.scene.numentities;i++)
13669                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13670
13671         r_refdef.stats.totaldecals += numdecals;
13672
13673         if (r_showsurfaces.integer)
13674                 return;
13675
13676         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13677
13678         for (i = 0;i < r_refdef.scene.numentities;i++)
13679         {
13680                 if (!r_refdef.viewcache.entityvisible[i])
13681                         continue;
13682                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13683                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13684         }
13685 }
13686
13687 extern cvar_t mod_collision_bih;
13688 void R_DrawDebugModel(void)
13689 {
13690         entity_render_t *ent = rsurface.entity;
13691         int i, j, k, l, flagsmask;
13692         const msurface_t *surface;
13693         dp_model_t *model = ent->model;
13694         vec3_t v;
13695
13696         switch(vid.renderpath)
13697         {
13698         case RENDERPATH_GL11:
13699         case RENDERPATH_GL13:
13700         case RENDERPATH_GL20:
13701         case RENDERPATH_CGGL:
13702                 break;
13703         case RENDERPATH_D3D9:
13704                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13705                 return;
13706         case RENDERPATH_D3D10:
13707                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13708                 return;
13709         case RENDERPATH_D3D11:
13710                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13711                 return;
13712         }
13713
13714         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13715
13716         R_Mesh_ResetTextureState();
13717         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13718         GL_DepthRange(0, 1);
13719         GL_DepthTest(!r_showdisabledepthtest.integer);
13720         GL_DepthMask(false);
13721         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13722
13723         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13724         {
13725                 int triangleindex;
13726                 int bihleafindex;
13727                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13728                 const q3mbrush_t *brush;
13729                 const bih_t *bih = &model->collision_bih;
13730                 const bih_leaf_t *bihleaf;
13731                 float vertex3f[3][3];
13732                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13733                 cullbox = false;
13734                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13735                 {
13736                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13737                                 continue;
13738                         switch (bihleaf->type)
13739                         {
13740                         case BIH_BRUSH:
13741                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13742                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13743                                 {
13744                                         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);
13745                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13746                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13747                                 }
13748                                 break;
13749                         case BIH_COLLISIONTRIANGLE:
13750                                 triangleindex = bihleaf->itemindex;
13751                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13752                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13753                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13754                                 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);
13755                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13756                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13757                                 break;
13758                         case BIH_RENDERTRIANGLE:
13759                                 triangleindex = bihleaf->itemindex;
13760                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13761                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13762                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13763                                 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);
13764                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13765                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13766                                 break;
13767                         }
13768                 }
13769         }
13770
13771         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13772
13773         if (r_showtris.integer || r_shownormals.integer)
13774         {
13775                 if (r_showdisabledepthtest.integer)
13776                 {
13777                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13778                         GL_DepthMask(false);
13779                 }
13780                 else
13781                 {
13782                         GL_BlendFunc(GL_ONE, GL_ZERO);
13783                         GL_DepthMask(true);
13784                 }
13785                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13786                 {
13787                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13788                                 continue;
13789                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13790                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13791                         {
13792                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13793                                 if (r_showtris.value > 0)
13794                                 {
13795                                         if (!rsurface.texture->currentlayers->depthmask)
13796                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13797                                         else if (ent == r_refdef.scene.worldentity)
13798                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13799                                         else
13800                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13801                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13802                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13803                                         RSurf_DrawBatch();
13804                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13805                                         CHECKGLERROR
13806                                 }
13807                                 if (r_shownormals.value < 0)
13808                                 {
13809                                         qglBegin(GL_LINES);
13810                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13811                                         {
13812                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13813                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13814                                                 qglVertex3f(v[0], v[1], v[2]);
13815                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13816                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13817                                                 qglVertex3f(v[0], v[1], v[2]);
13818                                         }
13819                                         qglEnd();
13820                                         CHECKGLERROR
13821                                 }
13822                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13823                                 {
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(r_refdef.view.colorscale, 0, 0, 1);
13829                                                 qglVertex3f(v[0], v[1], v[2]);
13830                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + 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                                         qglBegin(GL_LINES);
13837                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13838                                         {
13839                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13840                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13841                                                 qglVertex3f(v[0], v[1], v[2]);
13842                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13843                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13844                                                 qglVertex3f(v[0], v[1], v[2]);
13845                                         }
13846                                         qglEnd();
13847                                         CHECKGLERROR
13848                                         qglBegin(GL_LINES);
13849                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13850                                         {
13851                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13852                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13853                                                 qglVertex3f(v[0], v[1], v[2]);
13854                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13855                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13856                                                 qglVertex3f(v[0], v[1], v[2]);
13857                                         }
13858                                         qglEnd();
13859                                         CHECKGLERROR
13860                                 }
13861                         }
13862                 }
13863                 rsurface.texture = NULL;
13864         }
13865 }
13866
13867 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13868 int r_maxsurfacelist = 0;
13869 const msurface_t **r_surfacelist = NULL;
13870 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13871 {
13872         int i, j, endj, flagsmask;
13873         dp_model_t *model = r_refdef.scene.worldmodel;
13874         msurface_t *surfaces;
13875         unsigned char *update;
13876         int numsurfacelist = 0;
13877         if (model == NULL)
13878                 return;
13879
13880         if (r_maxsurfacelist < model->num_surfaces)
13881         {
13882                 r_maxsurfacelist = model->num_surfaces;
13883                 if (r_surfacelist)
13884                         Mem_Free((msurface_t**)r_surfacelist);
13885                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13886         }
13887
13888         RSurf_ActiveWorldEntity();
13889
13890         surfaces = model->data_surfaces;
13891         update = model->brushq1.lightmapupdateflags;
13892
13893         // update light styles on this submodel
13894         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13895         {
13896                 model_brush_lightstyleinfo_t *style;
13897                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13898                 {
13899                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13900                         {
13901                                 int *list = style->surfacelist;
13902                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13903                                 for (j = 0;j < style->numsurfaces;j++)
13904                                         update[list[j]] = true;
13905                         }
13906                 }
13907         }
13908
13909         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13910
13911         if (debug)
13912         {
13913                 R_DrawDebugModel();
13914                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13915                 return;
13916         }
13917
13918         rsurface.lightmaptexture = NULL;
13919         rsurface.deluxemaptexture = NULL;
13920         rsurface.uselightmaptexture = false;
13921         rsurface.texture = NULL;
13922         rsurface.rtlight = NULL;
13923         numsurfacelist = 0;
13924         // add visible surfaces to draw list
13925         for (i = 0;i < model->nummodelsurfaces;i++)
13926         {
13927                 j = model->sortedmodelsurfaces[i];
13928                 if (r_refdef.viewcache.world_surfacevisible[j])
13929                         r_surfacelist[numsurfacelist++] = surfaces + j;
13930         }
13931         // update lightmaps if needed
13932         if (model->brushq1.firstrender)
13933         {
13934                 model->brushq1.firstrender = false;
13935                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13936                         if (update[j])
13937                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13938         }
13939         else if (update)
13940         {
13941                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13942                         if (r_refdef.viewcache.world_surfacevisible[j])
13943                                 if (update[j])
13944                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13945         }
13946         // don't do anything if there were no surfaces
13947         if (!numsurfacelist)
13948         {
13949                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13950                 return;
13951         }
13952         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13953         GL_AlphaTest(false);
13954
13955         // add to stats if desired
13956         if (r_speeds.integer && !skysurfaces && !depthonly)
13957         {
13958                 r_refdef.stats.world_surfaces += numsurfacelist;
13959                 for (j = 0;j < numsurfacelist;j++)
13960                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13961         }
13962
13963         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13964 }
13965
13966 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13967 {
13968         int i, j, endj, flagsmask;
13969         dp_model_t *model = ent->model;
13970         msurface_t *surfaces;
13971         unsigned char *update;
13972         int numsurfacelist = 0;
13973         if (model == NULL)
13974                 return;
13975
13976         if (r_maxsurfacelist < model->num_surfaces)
13977         {
13978                 r_maxsurfacelist = model->num_surfaces;
13979                 if (r_surfacelist)
13980                         Mem_Free((msurface_t **)r_surfacelist);
13981                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13982         }
13983
13984         // if the model is static it doesn't matter what value we give for
13985         // wantnormals and wanttangents, so this logic uses only rules applicable
13986         // to a model, knowing that they are meaningless otherwise
13987         if (ent == r_refdef.scene.worldentity)
13988                 RSurf_ActiveWorldEntity();
13989         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13990                 RSurf_ActiveModelEntity(ent, false, false, false);
13991         else if (prepass)
13992                 RSurf_ActiveModelEntity(ent, true, true, true);
13993         else if (depthonly)
13994         {
13995                 switch (vid.renderpath)
13996                 {
13997                 case RENDERPATH_GL20:
13998                 case RENDERPATH_CGGL:
13999                 case RENDERPATH_D3D9:
14000                 case RENDERPATH_D3D10:
14001                 case RENDERPATH_D3D11:
14002                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14003                         break;
14004                 case RENDERPATH_GL13:
14005                 case RENDERPATH_GL11:
14006                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14007                         break;
14008                 }
14009         }
14010         else
14011         {
14012                 switch (vid.renderpath)
14013                 {
14014                 case RENDERPATH_GL20:
14015                 case RENDERPATH_CGGL:
14016                 case RENDERPATH_D3D9:
14017                 case RENDERPATH_D3D10:
14018                 case RENDERPATH_D3D11:
14019                         RSurf_ActiveModelEntity(ent, true, true, false);
14020                         break;
14021                 case RENDERPATH_GL13:
14022                 case RENDERPATH_GL11:
14023                         RSurf_ActiveModelEntity(ent, true, false, false);
14024                         break;
14025                 }
14026         }
14027
14028         surfaces = model->data_surfaces;
14029         update = model->brushq1.lightmapupdateflags;
14030
14031         // update light styles
14032         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14033         {
14034                 model_brush_lightstyleinfo_t *style;
14035                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14036                 {
14037                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14038                         {
14039                                 int *list = style->surfacelist;
14040                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14041                                 for (j = 0;j < style->numsurfaces;j++)
14042                                         update[list[j]] = true;
14043                         }
14044                 }
14045         }
14046
14047         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14048
14049         if (debug)
14050         {
14051                 R_DrawDebugModel();
14052                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14053                 return;
14054         }
14055
14056         rsurface.lightmaptexture = NULL;
14057         rsurface.deluxemaptexture = NULL;
14058         rsurface.uselightmaptexture = false;
14059         rsurface.texture = NULL;
14060         rsurface.rtlight = NULL;
14061         numsurfacelist = 0;
14062         // add visible surfaces to draw list
14063         for (i = 0;i < model->nummodelsurfaces;i++)
14064                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14065         // don't do anything if there were no surfaces
14066         if (!numsurfacelist)
14067         {
14068                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14069                 return;
14070         }
14071         // update lightmaps if needed
14072         if (update)
14073         {
14074                 int updated = 0;
14075                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14076                 {
14077                         if (update[j])
14078                         {
14079                                 updated++;
14080                                 R_BuildLightMap(ent, surfaces + j);
14081                         }
14082                 }
14083         }
14084         if (update)
14085                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14086                         if (update[j])
14087                                 R_BuildLightMap(ent, surfaces + j);
14088         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14089         GL_AlphaTest(false);
14090
14091         // add to stats if desired
14092         if (r_speeds.integer && !skysurfaces && !depthonly)
14093         {
14094                 r_refdef.stats.entities_surfaces += numsurfacelist;
14095                 for (j = 0;j < numsurfacelist;j++)
14096                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14097         }
14098
14099         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14100 }
14101
14102 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14103 {
14104         static texture_t texture;
14105         static msurface_t surface;
14106         const msurface_t *surfacelist = &surface;
14107
14108         // fake enough texture and surface state to render this geometry
14109
14110         texture.update_lastrenderframe = -1; // regenerate this texture
14111         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14112         texture.currentskinframe = skinframe;
14113         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14114         texture.offsetmapping = OFFSETMAPPING_OFF;
14115         texture.offsetscale = 1;
14116         texture.specularscalemod = 1;
14117         texture.specularpowermod = 1;
14118
14119         surface.texture = &texture;
14120         surface.num_triangles = numtriangles;
14121         surface.num_firsttriangle = firsttriangle;
14122         surface.num_vertices = numvertices;
14123         surface.num_firstvertex = firstvertex;
14124
14125         // now render it
14126         rsurface.texture = R_GetCurrentTexture(surface.texture);
14127         rsurface.lightmaptexture = NULL;
14128         rsurface.deluxemaptexture = NULL;
14129         rsurface.uselightmaptexture = false;
14130         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14131 }
14132
14133 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)
14134 {
14135         static msurface_t surface;
14136         const msurface_t *surfacelist = &surface;
14137
14138         // fake enough texture and surface state to render this geometry
14139
14140         surface.texture = texture;
14141         surface.num_triangles = numtriangles;
14142         surface.num_firsttriangle = firsttriangle;
14143         surface.num_vertices = numvertices;
14144         surface.num_firstvertex = firstvertex;
14145
14146         // now render it
14147         rsurface.texture = R_GetCurrentTexture(surface.texture);
14148         rsurface.lightmaptexture = NULL;
14149         rsurface.deluxemaptexture = NULL;
14150         rsurface.uselightmaptexture = false;
14151         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14152 }