]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
allow .alpha to fade out water/refraction/reflection surfaces (only tested on refract...
[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 "#ifdef USEDIFFUSE\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "#endif\n"
2008 "#ifdef USESPECULAR\n"
2009 "out float2 TexCoord2 : TEXCOORD1,\n"
2010 "#endif\n"
2011 "out float4 gl_FrontColor : COLOR\n"
2012 ")\n"
2013 "{\n"
2014 "#ifdef HLSL\n"
2015 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2016 "#else\n"
2017 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2018 "#endif\n"
2019 "#ifdef USEDIFFUSE\n"
2020 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2021 "#endif\n"
2022 "#ifdef USESPECULAR\n"
2023 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2024 "#endif\n"
2025 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2026 "}\n"
2027 "#endif\n"
2028 "\n"
2029 "#ifdef FRAGMENT_SHADER\n"
2030 "\n"
2031 "void main\n"
2032 "(\n"
2033 "float4 gl_FrontColor : COLOR0,\n"
2034 "float2 TexCoord1 : TEXCOORD0,\n"
2035 "float2 TexCoord2 : TEXCOORD1,\n"
2036 "#ifdef USEDIFFUSE\n"
2037 "uniform sampler Texture_First : register(s0),\n"
2038 "#endif\n"
2039 "#ifdef USESPECULAR\n"
2040 "uniform sampler Texture_Second : register(s1),\n"
2041 "#endif\n"
2042 "out float4 gl_FragColor : COLOR\n"
2043 ")\n"
2044 "{\n"
2045 "       gl_FragColor = gl_FrontColor;\n"
2046 "#ifdef USEDIFFUSE\n"
2047 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2048 "#endif\n"
2049 "\n"
2050 "#ifdef USESPECULAR\n"
2051 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2052 "# ifdef USECOLORMAPPING\n"
2053 "       gl_FragColor *= tex2;\n"
2054 "# endif\n"
2055 "# ifdef USEGLOW\n"
2056 "       gl_FragColor += tex2;\n"
2057 "# endif\n"
2058 "# ifdef USEVERTEXTEXTUREBLEND\n"
2059 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2060 "# endif\n"
2061 "#endif\n"
2062 "}\n"
2063 "#endif\n"
2064 "#else // !MODE_GENERIC\n"
2065 "\n"
2066 "\n"
2067 "\n"
2068 "\n"
2069 "#ifdef MODE_BLOOMBLUR\n"
2070 "#ifdef VERTEX_SHADER\n"
2071 "void main\n"
2072 "(\n"
2073 "float4 gl_Vertex : POSITION,\n"
2074 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2075 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2076 "out float4 gl_Position : POSITION,\n"
2077 "out float2 TexCoord : TEXCOORD0\n"
2078 ")\n"
2079 "{\n"
2080 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2081 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2082 "}\n"
2083 "#endif\n"
2084 "\n"
2085 "#ifdef FRAGMENT_SHADER\n"
2086 "\n"
2087 "void main\n"
2088 "(\n"
2089 "float2 TexCoord : TEXCOORD0,\n"
2090 "uniform sampler Texture_First : register(s0),\n"
2091 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2092 "out float4 gl_FragColor : COLOR\n"
2093 ")\n"
2094 "{\n"
2095 "       int i;\n"
2096 "       float2 tc = TexCoord;\n"
2097 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2098 "       tc += BloomBlur_Parameters.xy;\n"
2099 "       for (i = 1;i < SAMPLES;i++)\n"
2100 "       {\n"
2101 "               color += tex2D(Texture_First, tc).rgb;\n"
2102 "               tc += BloomBlur_Parameters.xy;\n"
2103 "       }\n"
2104 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2105 "}\n"
2106 "#endif\n"
2107 "#else // !MODE_BLOOMBLUR\n"
2108 "#ifdef MODE_REFRACTION\n"
2109 "#ifdef VERTEX_SHADER\n"
2110 "void main\n"
2111 "(\n"
2112 "float4 gl_Vertex : POSITION,\n"
2113 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2114 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2115 "uniform float4x4 TexMatrix : register(c0),\n"
2116 "uniform float3 EyePosition : register(c24),\n"
2117 "out float4 gl_Position : POSITION,\n"
2118 "out float2 TexCoord : TEXCOORD0,\n"
2119 "out float3 EyeVector : TEXCOORD1,\n"
2120 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2121 ")\n"
2122 "{\n"
2123 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2124 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2125 "       ModelViewProjectionPosition = gl_Position;\n"
2126 "}\n"
2127 "#endif\n"
2128 "\n"
2129 "#ifdef FRAGMENT_SHADER\n"
2130 "void main\n"
2131 "(\n"
2132 "float2 TexCoord : TEXCOORD0,\n"
2133 "float3 EyeVector : TEXCOORD1,\n"
2134 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2135 "uniform sampler Texture_Normal : register(s0),\n"
2136 "uniform sampler Texture_Refraction : register(s3),\n"
2137 "uniform sampler Texture_Reflection : register(s7),\n"
2138 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2139 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2140 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2141 "uniform float4 RefractColor : register(c29),\n"
2142 "out float4 gl_FragColor : COLOR\n"
2143 ")\n"
2144 "{\n"
2145 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2146 "       //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"
2147 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2148 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2149 "       // FIXME temporary hack to detect the case that the reflection\n"
2150 "       // gets blackened at edges due to leaving the area that contains actual\n"
2151 "       // content.\n"
2152 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2153 "       // 'appening.\n"
2154 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2155 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2156 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2157 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2158 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2159 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2160 "}\n"
2161 "#endif\n"
2162 "#else // !MODE_REFRACTION\n"
2163 "\n"
2164 "\n"
2165 "\n"
2166 "\n"
2167 "#ifdef MODE_WATER\n"
2168 "#ifdef VERTEX_SHADER\n"
2169 "\n"
2170 "void main\n"
2171 "(\n"
2172 "float4 gl_Vertex : POSITION,\n"
2173 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2174 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2175 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2176 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2177 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2178 "uniform float4x4 TexMatrix : register(c0),\n"
2179 "uniform float3 EyePosition : register(c24),\n"
2180 "out float4 gl_Position : POSITION,\n"
2181 "out float2 TexCoord : TEXCOORD0,\n"
2182 "out float3 EyeVector : TEXCOORD1,\n"
2183 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2184 ")\n"
2185 "{\n"
2186 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2187 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2188 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2189 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2190 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2191 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2192 "       ModelViewProjectionPosition = gl_Position;\n"
2193 "}\n"
2194 "#endif\n"
2195 "\n"
2196 "#ifdef FRAGMENT_SHADER\n"
2197 "void main\n"
2198 "(\n"
2199 "float2 TexCoord : TEXCOORD0,\n"
2200 "float3 EyeVector : TEXCOORD1,\n"
2201 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2202 "uniform sampler Texture_Normal : register(s0),\n"
2203 "uniform sampler Texture_Refraction : register(s3),\n"
2204 "uniform sampler Texture_Reflection : register(s7),\n"
2205 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2206 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2207 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2208 "uniform float4 RefractColor : register(c29),\n"
2209 "uniform float4 ReflectColor : register(c26),\n"
2210 "uniform float ReflectFactor : register(c27),\n"
2211 "uniform float ReflectOffset : register(c28),\n"
2212 "out float4 gl_FragColor : COLOR\n"
2213 ")\n"
2214 "{\n"
2215 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2216 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2217 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2218 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2219 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2220 "       // FIXME temporary hack to detect the case that the reflection\n"
2221 "       // gets blackened at edges due to leaving the area that contains actual\n"
2222 "       // content.\n"
2223 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2224 "       // 'appening.\n"
2225 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2226 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2227 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2228 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2229 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2230 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2231 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2232 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2233 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2234 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2235 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2236 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2237 "}\n"
2238 "#endif\n"
2239 "#else // !MODE_WATER\n"
2240 "\n"
2241 "\n"
2242 "\n"
2243 "\n"
2244 "// 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"
2245 "\n"
2246 "// fragment shader specific:\n"
2247 "#ifdef FRAGMENT_SHADER\n"
2248 "\n"
2249 "#ifdef USEFOG\n"
2250 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2251 "{\n"
2252 "       float fogfrac;\n"
2253 "#ifdef USEFOGHEIGHTTEXTURE\n"
2254 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2255 "       fogfrac = fogheightpixel.a;\n"
2256 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2257 "#else\n"
2258 "# ifdef USEFOGOUTSIDE\n"
2259 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2260 "# else\n"
2261 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2262 "# endif\n"
2263 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2264 "#endif\n"
2265 "}\n"
2266 "#endif\n"
2267 "\n"
2268 "#ifdef USEOFFSETMAPPING\n"
2269 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2270 "{\n"
2271 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2272 "       // 14 sample relief mapping: linear search and then binary search\n"
2273 "       // this basically steps forward a small amount repeatedly until it finds\n"
2274 "       // itself inside solid, then jitters forward and back using decreasing\n"
2275 "       // amounts to find the impact\n"
2276 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2277 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2278 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2279 "       float3 RT = float3(TexCoord, 1);\n"
2280 "       OffsetVector *= 0.1;\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);\n"
2287 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2288 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2289 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2290 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2291 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2292 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2293 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2294 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2295 "       return RT.xy;\n"
2296 "#else\n"
2297 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2298 "       // this basically moves forward the full distance, and then backs up based\n"
2299 "       // on height of samples\n"
2300 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2301 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2302 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2303 "       TexCoord += OffsetVector;\n"
2304 "       OffsetVector *= 0.333;\n"
2305 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2306 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2307 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2308 "       return TexCoord;\n"
2309 "#endif\n"
2310 "}\n"
2311 "#endif // USEOFFSETMAPPING\n"
2312 "\n"
2313 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2314 "#if defined(USESHADOWMAP2D)\n"
2315 "# ifdef USESHADOWMAPORTHO\n"
2316 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2317 "# else\n"
2318 "#  ifdef USESHADOWMAPVSDCT\n"
2319 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2320 "{\n"
2321 "       float3 adir = abs(dir);\n"
2322 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2323 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2324 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2325 "}\n"
2326 "#  else\n"
2327 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2328 "{\n"
2329 "       float3 adir = abs(dir);\n"
2330 "       float ma = adir.z;\n"
2331 "       float4 proj = float4(dir, 2.5);\n"
2332 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2333 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2334 "#ifdef HLSL\n"
2335 "       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"
2336 "#else\n"
2337 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2338 "       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"
2339 "#endif\n"
2340 "}\n"
2341 "#  endif\n"
2342 "# endif\n"
2343 "#endif // defined(USESHADOWMAP2D)\n"
2344 "\n"
2345 "# ifdef USESHADOWMAP2D\n"
2346 "#ifdef USESHADOWMAPVSDCT\n"
2347 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2348 "#else\n"
2349 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2350 "#endif\n"
2351 "{\n"
2352 "#ifdef USESHADOWMAPVSDCT\n"
2353 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2354 "#else\n"
2355 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2356 "#endif\n"
2357 "       float f;\n"
2358 "\n"
2359 "#  ifdef USESHADOWSAMPLER\n"
2360 "#    ifdef USESHADOWMAPPCF\n"
2361 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2362 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2363 "       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"
2364 "#    else\n"
2365 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2366 "#    endif\n"
2367 "#  else\n"
2368 "#    ifdef USESHADOWMAPPCF\n"
2369 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2370 "#      ifdef GL_ARB_texture_gather\n"
2371 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2372 "#      else\n"
2373 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2374 "#      endif\n"
2375 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2376 "#      if USESHADOWMAPPCF > 1\n"
2377 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2378 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2379 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2380 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2381 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2382 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2383 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2384 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2385 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2386 "       float4 locols = float4(group1.ab, group3.ab);\n"
2387 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2388 "       locols.yz += group2.ab;\n"
2389 "       hicols.yz += group8.rg;\n"
2390 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2391 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2392 "                               lerp(locols, hicols, offset.y);\n"
2393 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2394 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2395 "       f = dot(cols, float4(1.0/25.0));\n"
2396 "#      else\n"
2397 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2398 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2399 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2400 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2401 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2402 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2403 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2404 "#      endif\n"
2405 "#     else\n"
2406 "#      ifdef GL_EXT_gpu_shader4\n"
2407 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2408 "#      else\n"
2409 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2410 "#      endif\n"
2411 "#      if USESHADOWMAPPCF > 1\n"
2412 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2413 "       center *= ShadowMap_TextureScale;\n"
2414 "       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"
2415 "       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"
2416 "       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"
2417 "       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"
2418 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2419 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2420 "#      else\n"
2421 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2422 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2423 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2424 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2425 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2426 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2427 "#      endif\n"
2428 "#     endif\n"
2429 "#    else\n"
2430 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2431 "#    endif\n"
2432 "#  endif\n"
2433 "#  ifdef USESHADOWMAPORTHO\n"
2434 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2435 "#  else\n"
2436 "       return f;\n"
2437 "#  endif\n"
2438 "}\n"
2439 "# endif\n"
2440 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2441 "#endif // FRAGMENT_SHADER\n"
2442 "\n"
2443 "\n"
2444 "\n"
2445 "\n"
2446 "#ifdef MODE_DEFERREDGEOMETRY\n"
2447 "#ifdef VERTEX_SHADER\n"
2448 "void main\n"
2449 "(\n"
2450 "float4 gl_Vertex : POSITION,\n"
2451 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2452 "#ifdef USEVERTEXTEXTUREBLEND\n"
2453 "float4 gl_Color : COLOR0,\n"
2454 "#endif\n"
2455 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2456 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2457 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2458 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2459 "uniform float4x4 TexMatrix : register(c0),\n"
2460 "#ifdef USEVERTEXTEXTUREBLEND\n"
2461 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2462 "#endif\n"
2463 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2464 "#ifdef USEOFFSETMAPPING\n"
2465 "uniform float3 EyePosition : register(c24),\n"
2466 "#endif\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "#ifdef USEVERTEXTEXTUREBLEND\n"
2469 "out float4 gl_FrontColor : COLOR,\n"
2470 "#endif\n"
2471 "out float4 TexCoordBoth : TEXCOORD0,\n"
2472 "#ifdef USEOFFSETMAPPING\n"
2473 "out float3 EyeVector : TEXCOORD2,\n"
2474 "#endif\n"
2475 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2476 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2477 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2478 ")\n"
2479 "{\n"
2480 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2481 "#ifdef USEVERTEXTEXTUREBLEND\n"
2482 "#ifdef HLSL\n"
2483 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2484 "#else\n"
2485 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2486 "#endif\n"
2487 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2488 "#endif\n"
2489 "\n"
2490 "       // transform unnormalized eye direction into tangent space\n"
2491 "#ifdef USEOFFSETMAPPING\n"
2492 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2493 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2494 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2495 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2496 "#endif\n"
2497 "\n"
2498 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2499 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2500 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2501 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2502 "       VectorR.w = gl_Position.z;\n"
2503 "}\n"
2504 "#endif // VERTEX_SHADER\n"
2505 "\n"
2506 "#ifdef FRAGMENT_SHADER\n"
2507 "void main\n"
2508 "(\n"
2509 "float4 TexCoordBoth : TEXCOORD0,\n"
2510 "float3 EyeVector : TEXCOORD2,\n"
2511 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2512 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2513 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2514 "uniform sampler Texture_Normal : register(s0),\n"
2515 "#ifdef USEALPHAKILL\n"
2516 "uniform sampler Texture_Color : register(s1),\n"
2517 "#endif\n"
2518 "uniform sampler Texture_Gloss : register(s2),\n"
2519 "#ifdef USEVERTEXTEXTUREBLEND\n"
2520 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2521 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2522 "#endif\n"
2523 "#ifdef USEOFFSETMAPPING\n"
2524 "uniform float OffsetMapping_Scale : register(c24),\n"
2525 "#endif\n"
2526 "uniform half SpecularPower : register(c36),\n"
2527 "#ifdef HLSL\n"
2528 "out float4 gl_FragData0 : COLOR0,\n"
2529 "out float4 gl_FragData1 : COLOR1\n"
2530 "#else\n"
2531 "out float4 gl_FragColor : COLOR\n"
2532 "#endif\n"
2533 ")\n"
2534 "{\n"
2535 "       float2 TexCoord = TexCoordBoth.xy;\n"
2536 "#ifdef USEOFFSETMAPPING\n"
2537 "       // apply offsetmapping\n"
2538 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2539 "#define TexCoord TexCoordOffset\n"
2540 "#endif\n"
2541 "\n"
2542 "#ifdef USEALPHAKILL\n"
2543 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2544 "               discard;\n"
2545 "#endif\n"
2546 "\n"
2547 "#ifdef USEVERTEXTEXTUREBLEND\n"
2548 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2549 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2550 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2551 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2552 "#endif\n"
2553 "\n"
2554 "#ifdef USEVERTEXTEXTUREBLEND\n"
2555 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2556 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2557 "#else\n"
2558 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2559 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2560 "#endif\n"
2561 "\n"
2562 "#ifdef HLSL\n"
2563 "       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"
2564 "       float Depth = VectorR.w / 256.0;\n"
2565 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2566 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2567 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2568 "       gl_FragData1 = depthcolor;\n"
2569 "#else\n"
2570 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2571 "#endif\n"
2572 "}\n"
2573 "#endif // FRAGMENT_SHADER\n"
2574 "#else // !MODE_DEFERREDGEOMETRY\n"
2575 "\n"
2576 "\n"
2577 "\n"
2578 "\n"
2579 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2580 "#ifdef VERTEX_SHADER\n"
2581 "void main\n"
2582 "(\n"
2583 "float4 gl_Vertex : POSITION,\n"
2584 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2585 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2586 "out float4 gl_Position : POSITION,\n"
2587 "out float4 ModelViewPosition : TEXCOORD0\n"
2588 ")\n"
2589 "{\n"
2590 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2591 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2592 "}\n"
2593 "#endif // VERTEX_SHADER\n"
2594 "\n"
2595 "#ifdef FRAGMENT_SHADER\n"
2596 "void main\n"
2597 "(\n"
2598 "#ifdef HLSL\n"
2599 "float2 Pixel : VPOS,\n"
2600 "#else\n"
2601 "float2 Pixel : WPOS,\n"
2602 "#endif\n"
2603 "float4 ModelViewPosition : TEXCOORD0,\n"
2604 "uniform float4x4 ViewToLight : register(c44),\n"
2605 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2606 "uniform float3 LightPosition : register(c23),\n"
2607 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2608 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2609 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2610 "#ifdef USESPECULAR\n"
2611 "uniform half3 DeferredColor_Specular : register(c11),\n"
2612 "uniform half SpecularPower : register(c36),\n"
2613 "#endif\n"
2614 "uniform sampler Texture_Attenuation : register(s9),\n"
2615 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2616 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2617 "\n"
2618 "#ifdef USECUBEFILTER\n"
2619 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2620 "#endif\n"
2621 "\n"
2622 "#ifdef USESHADOWMAP2D\n"
2623 "# ifdef USESHADOWSAMPLER\n"
2624 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2625 "# else\n"
2626 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2627 "# endif\n"
2628 "#endif\n"
2629 "\n"
2630 "#ifdef USESHADOWMAPVSDCT\n"
2631 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2632 "#endif\n"
2633 "\n"
2634 "#if defined(USESHADOWMAP2D)\n"
2635 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2636 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2637 "#endif\n"
2638 "\n"
2639 "out float4 gl_FragData0 : COLOR0,\n"
2640 "out float4 gl_FragData1 : COLOR1\n"
2641 ")\n"
2642 "{\n"
2643 "       // calculate viewspace pixel position\n"
2644 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2645 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2646 "       float3 position;\n"
2647 "#ifdef HLSL\n"
2648 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2649 "#else\n"
2650 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2651 "#endif\n"
2652 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2653 "       // decode viewspace pixel normal\n"
2654 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2655 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2656 "       // surfacenormal = pixel normal in viewspace\n"
2657 "       // LightVector = pixel to light in viewspace\n"
2658 "       // CubeVector = position in lightspace\n"
2659 "       // eyevector = pixel to view in viewspace\n"
2660 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2661 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2662 "#ifdef USEDIFFUSE\n"
2663 "       // calculate diffuse shading\n"
2664 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2665 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2666 "#endif\n"
2667 "#ifdef USESPECULAR\n"
2668 "       // calculate directional shading\n"
2669 "       float3 eyevector = position * -1.0;\n"
2670 "#  ifdef USEEXACTSPECULARMATH\n"
2671 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2672 "#  else\n"
2673 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2674 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2675 "#  endif\n"
2676 "#endif\n"
2677 "\n"
2678 "#if defined(USESHADOWMAP2D)\n"
2679 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2680 "#ifdef USESHADOWMAPVSDCT\n"
2681 ", Texture_CubeProjection\n"
2682 "#endif\n"
2683 "       ));\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef USEDIFFUSE\n"
2687 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2688 "#else\n"
2689 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2690 "#endif\n"
2691 "#ifdef USESPECULAR\n"
2692 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2693 "#else\n"
2694 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2695 "#endif\n"
2696 "\n"
2697 "# ifdef USECUBEFILTER\n"
2698 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2699 "       gl_FragData0.rgb *= cubecolor;\n"
2700 "       gl_FragData1.rgb *= cubecolor;\n"
2701 "# endif\n"
2702 "}\n"
2703 "#endif // FRAGMENT_SHADER\n"
2704 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2705 "\n"
2706 "\n"
2707 "\n"
2708 "\n"
2709 "#ifdef VERTEX_SHADER\n"
2710 "void main\n"
2711 "(\n"
2712 "float4 gl_Vertex : POSITION,\n"
2713 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2714 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2715 "float4 gl_Color : COLOR0,\n"
2716 "#endif\n"
2717 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2718 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2719 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2720 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2721 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2722 "\n"
2723 "uniform float3 EyePosition : register(c24),\n"
2724 "uniform float4x4 TexMatrix : register(c0),\n"
2725 "#ifdef USEVERTEXTEXTUREBLEND\n"
2726 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2727 "#endif\n"
2728 "#ifdef MODE_LIGHTSOURCE\n"
2729 "uniform float4x4 ModelToLight : register(c20),\n"
2730 "#endif\n"
2731 "#ifdef MODE_LIGHTSOURCE\n"
2732 "uniform float3 LightPosition : register(c27),\n"
2733 "#endif\n"
2734 "#ifdef MODE_LIGHTDIRECTION\n"
2735 "uniform float3 LightDir : register(c26),\n"
2736 "#endif\n"
2737 "uniform float4 FogPlane : register(c25),\n"
2738 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2739 "uniform float3 LightPosition : register(c27),\n"
2740 "#endif\n"
2741 "#ifdef USESHADOWMAPORTHO\n"
2742 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2743 "#endif\n"
2744 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2745 "out float4 gl_FrontColor : COLOR,\n"
2746 "#endif\n"
2747 "out float4 TexCoordBoth : TEXCOORD0,\n"
2748 "#ifdef USELIGHTMAP\n"
2749 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2750 "#endif\n"
2751 "#ifdef USEEYEVECTOR\n"
2752 "out float3 EyeVector : TEXCOORD2,\n"
2753 "#endif\n"
2754 "#ifdef USEREFLECTION\n"
2755 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2756 "#endif\n"
2757 "#ifdef USEFOG\n"
2758 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2759 "#endif\n"
2760 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2761 "out float3 LightVector : TEXCOORD1,\n"
2762 "#endif\n"
2763 "#ifdef MODE_LIGHTSOURCE\n"
2764 "out float3 CubeVector : TEXCOORD3,\n"
2765 "#endif\n"
2766 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2767 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2768 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2769 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2770 "#endif\n"
2771 "#ifdef USESHADOWMAPORTHO\n"
2772 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2773 "#endif\n"
2774 "out float4 gl_Position : POSITION\n"
2775 ")\n"
2776 "{\n"
2777 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2778 "#ifdef HLSL\n"
2779 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2780 "#else\n"
2781 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2782 "#endif\n"
2783 "#endif\n"
2784 "       // copy the surface texcoord\n"
2785 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2786 "#ifdef USEVERTEXTEXTUREBLEND\n"
2787 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2788 "#endif\n"
2789 "#ifdef USELIGHTMAP\n"
2790 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2791 "#endif\n"
2792 "\n"
2793 "#ifdef MODE_LIGHTSOURCE\n"
2794 "       // transform vertex position into light attenuation/cubemap space\n"
2795 "       // (-1 to +1 across the light box)\n"
2796 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2797 "\n"
2798 "# ifdef USEDIFFUSE\n"
2799 "       // transform unnormalized light direction into tangent space\n"
2800 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2801 "       //  normalize it per pixel)\n"
2802 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2803 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2804 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2805 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2806 "# endif\n"
2807 "#endif\n"
2808 "\n"
2809 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2810 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2811 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2812 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2813 "#endif\n"
2814 "\n"
2815 "       // transform unnormalized eye direction into tangent space\n"
2816 "#ifdef USEEYEVECTOR\n"
2817 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2818 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2819 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2820 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2821 "#endif\n"
2822 "\n"
2823 "#ifdef USEFOG\n"
2824 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2825 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2826 "#endif\n"
2827 "\n"
2828 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2829 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2830 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2831 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2832 "#endif\n"
2833 "\n"
2834 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2835 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2836 "\n"
2837 "#ifdef USESHADOWMAPORTHO\n"
2838 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2839 "#endif\n"
2840 "\n"
2841 "#ifdef USEREFLECTION\n"
2842 "       ModelViewProjectionPosition = gl_Position;\n"
2843 "#endif\n"
2844 "}\n"
2845 "#endif // VERTEX_SHADER\n"
2846 "\n"
2847 "\n"
2848 "\n"
2849 "\n"
2850 "#ifdef FRAGMENT_SHADER\n"
2851 "void main\n"
2852 "(\n"
2853 "#ifdef USEDEFERREDLIGHTMAP\n"
2854 "#ifdef HLSL\n"
2855 "float2 Pixel : VPOS,\n"
2856 "#else\n"
2857 "float2 Pixel : WPOS,\n"
2858 "#endif\n"
2859 "#endif\n"
2860 "float4 gl_FrontColor : COLOR,\n"
2861 "float4 TexCoordBoth : TEXCOORD0,\n"
2862 "#ifdef USELIGHTMAP\n"
2863 "float2 TexCoordLightmap : TEXCOORD1,\n"
2864 "#endif\n"
2865 "#ifdef USEEYEVECTOR\n"
2866 "float3 EyeVector : TEXCOORD2,\n"
2867 "#endif\n"
2868 "#ifdef USEREFLECTION\n"
2869 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2870 "#endif\n"
2871 "#ifdef USEFOG\n"
2872 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2873 "#endif\n"
2874 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2875 "float3 LightVector : TEXCOORD1,\n"
2876 "#endif\n"
2877 "#ifdef MODE_LIGHTSOURCE\n"
2878 "float3 CubeVector : TEXCOORD3,\n"
2879 "#endif\n"
2880 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2881 "float4 ModelViewPosition : TEXCOORD0,\n"
2882 "#endif\n"
2883 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2884 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2885 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2886 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2887 "#endif\n"
2888 "#ifdef USESHADOWMAPORTHO\n"
2889 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2890 "#endif\n"
2891 "\n"
2892 "uniform sampler Texture_Normal : register(s0),\n"
2893 "uniform sampler Texture_Color : register(s1),\n"
2894 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2895 "uniform sampler Texture_Gloss : register(s2),\n"
2896 "#endif\n"
2897 "#ifdef USEGLOW\n"
2898 "uniform sampler Texture_Glow : register(s3),\n"
2899 "#endif\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2902 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2903 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2904 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2905 "#endif\n"
2906 "#ifdef USEGLOW\n"
2907 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2908 "#endif\n"
2909 "#endif\n"
2910 "#ifdef USECOLORMAPPING\n"
2911 "uniform sampler Texture_Pants : register(s4),\n"
2912 "uniform sampler Texture_Shirt : register(s7),\n"
2913 "#endif\n"
2914 "#ifdef USEFOG\n"
2915 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2916 "uniform sampler Texture_FogMask : register(s8),\n"
2917 "#endif\n"
2918 "#ifdef USELIGHTMAP\n"
2919 "uniform sampler Texture_Lightmap : register(s9),\n"
2920 "#endif\n"
2921 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2922 "uniform sampler Texture_Deluxemap : register(s10),\n"
2923 "#endif\n"
2924 "#ifdef USEREFLECTION\n"
2925 "uniform sampler Texture_Reflection : register(s7),\n"
2926 "#endif\n"
2927 "\n"
2928 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2929 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2930 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2931 "#endif\n"
2932 "#ifdef USEDEFERREDLIGHTMAP\n"
2933 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2934 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2935 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2936 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2937 "#endif\n"
2938 "\n"
2939 "#ifdef USECOLORMAPPING\n"
2940 "uniform half3 Color_Pants : register(c7),\n"
2941 "uniform half3 Color_Shirt : register(c8),\n"
2942 "#endif\n"
2943 "#ifdef USEFOG\n"
2944 "uniform float3 FogColor : register(c16),\n"
2945 "uniform float FogRangeRecip : register(c20),\n"
2946 "uniform float FogPlaneViewDist : register(c19),\n"
2947 "uniform float FogHeightFade : register(c17),\n"
2948 "#endif\n"
2949 "\n"
2950 "#ifdef USEOFFSETMAPPING\n"
2951 "uniform float OffsetMapping_Scale : register(c24),\n"
2952 "#endif\n"
2953 "\n"
2954 "#ifdef USEDEFERREDLIGHTMAP\n"
2955 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2956 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2957 "uniform half3 DeferredMod_Specular : register(c13),\n"
2958 "#endif\n"
2959 "uniform half3 Color_Ambient : register(c3),\n"
2960 "uniform half3 Color_Diffuse : register(c4),\n"
2961 "uniform half3 Color_Specular : register(c5),\n"
2962 "uniform half SpecularPower : register(c36),\n"
2963 "#ifdef USEGLOW\n"
2964 "uniform half3 Color_Glow : register(c6),\n"
2965 "#endif\n"
2966 "uniform half Alpha : register(c0),\n"
2967 "#ifdef USEREFLECTION\n"
2968 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2969 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2970 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2971 "uniform half4 ReflectColor : register(c26),\n"
2972 "#endif\n"
2973 "#ifdef USEREFLECTCUBE\n"
2974 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2975 "uniform sampler Texture_ReflectMask : register(s5),\n"
2976 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2977 "#endif\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "uniform half3 LightColor : register(c21),\n"
2980 "#endif\n"
2981 "#ifdef MODE_LIGHTSOURCE\n"
2982 "uniform half3 LightColor : register(c21),\n"
2983 "#endif\n"
2984 "\n"
2985 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2986 "uniform sampler Texture_Attenuation : register(s9),\n"
2987 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2988 "#endif\n"
2989 "\n"
2990 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2991 "\n"
2992 "#ifdef USESHADOWMAP2D\n"
2993 "# ifdef USESHADOWSAMPLER\n"
2994 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2995 "# else\n"
2996 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2997 "# endif\n"
2998 "#endif\n"
2999 "\n"
3000 "#ifdef USESHADOWMAPVSDCT\n"
3001 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3002 "#endif\n"
3003 "\n"
3004 "#if defined(USESHADOWMAP2D)\n"
3005 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3006 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3007 "#endif\n"
3008 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3009 "\n"
3010 "out float4 gl_FragColor : COLOR\n"
3011 ")\n"
3012 "{\n"
3013 "       float2 TexCoord = TexCoordBoth.xy;\n"
3014 "#ifdef USEVERTEXTEXTUREBLEND\n"
3015 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3016 "#endif\n"
3017 "#ifdef USEOFFSETMAPPING\n"
3018 "       // apply offsetmapping\n"
3019 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3020 "#define TexCoord TexCoordOffset\n"
3021 "#endif\n"
3022 "\n"
3023 "       // combine the diffuse textures (base, pants, shirt)\n"
3024 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3025 "#ifdef USEALPHAKILL\n"
3026 "       if (color.a < 0.5)\n"
3027 "               discard;\n"
3028 "#endif\n"
3029 "       color.a *= Alpha;\n"
3030 "#ifdef USECOLORMAPPING\n"
3031 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3032 "#endif\n"
3033 "#ifdef USEVERTEXTEXTUREBLEND\n"
3034 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3035 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3036 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3037 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3038 "       color.a = 1.0;\n"
3039 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3040 "#endif\n"
3041 "\n"
3042 "       // get the surface normal\n"
3043 "#ifdef USEVERTEXTEXTUREBLEND\n"
3044 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3045 "#else\n"
3046 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3047 "#endif\n"
3048 "\n"
3049 "       // get the material colors\n"
3050 "       half3 diffusetex = color.rgb;\n"
3051 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3052 "# ifdef USEVERTEXTEXTUREBLEND\n"
3053 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3054 "# else\n"
3055 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3056 "# endif\n"
3057 "#endif\n"
3058 "\n"
3059 "#ifdef USEREFLECTCUBE\n"
3060 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3061 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3062 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3063 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3064 "#endif\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "\n"
3069 "#ifdef MODE_LIGHTSOURCE\n"
3070 "       // light source\n"
3071 "#ifdef USEDIFFUSE\n"
3072 "       half3 lightnormal = half3(normalize(LightVector));\n"
3073 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3074 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3075 "#ifdef USESPECULAR\n"
3076 "#ifdef USEEXACTSPECULARMATH\n"
3077 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3078 "#else\n"
3079 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3080 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3081 "#endif\n"
3082 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3083 "#endif\n"
3084 "#else\n"
3085 "       color.rgb = diffusetex * Color_Ambient;\n"
3086 "#endif\n"
3087 "       color.rgb *= LightColor;\n"
3088 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3089 "#if defined(USESHADOWMAP2D)\n"
3090 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3091 "#ifdef USESHADOWMAPVSDCT\n"
3092 ", Texture_CubeProjection\n"
3093 "#endif\n"
3094 "       ));\n"
3095 "\n"
3096 "#endif\n"
3097 "# ifdef USECUBEFILTER\n"
3098 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3099 "# endif\n"
3100 "\n"
3101 "#ifdef USESHADOWMAP2D\n"
3102 "#ifdef USESHADOWMAPVSDCT\n"
3103 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3104 "#else\n"
3105 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3106 "#endif\n"
3107 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3108 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3109 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3110 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3111 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3112 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3113 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3114 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3115 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3116 "//     color.r = half(shadowmaptc.z);\n"
3117 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3118 "//     color.r = half(shadowmaptc.z);\n"
3119 "//     color.r = 1;\n"
3120 "//     color.rgb = abs(CubeVector);\n"
3121 "#endif\n"
3122 "//     color.rgb = half3(1,1,1);\n"
3123 "#endif // MODE_LIGHTSOURCE\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "\n"
3128 "#ifdef MODE_LIGHTDIRECTION\n"
3129 "#define SHADING\n"
3130 "#ifdef USEDIFFUSE\n"
3131 "       half3 lightnormal = half3(normalize(LightVector));\n"
3132 "#endif\n"
3133 "#define lightcolor LightColor\n"
3134 "#endif // MODE_LIGHTDIRECTION\n"
3135 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3136 "#define SHADING\n"
3137 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3138 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3139 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3140 "       // convert modelspace light vector to tangentspace\n"
3141 "       half3 lightnormal;\n"
3142 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3143 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3144 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3145 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3146 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3147 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3148 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3149 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3150 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3151 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3152 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3153 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3154 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3155 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3156 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3157 "#define SHADING\n"
3158 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3159 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3160 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3161 "#endif\n"
3162 "\n"
3163 "\n"
3164 "\n"
3165 "\n"
3166 "#ifdef MODE_LIGHTMAP\n"
3167 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3168 "#endif // MODE_LIGHTMAP\n"
3169 "#ifdef MODE_VERTEXCOLOR\n"
3170 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3171 "#endif // MODE_VERTEXCOLOR\n"
3172 "#ifdef MODE_FLATCOLOR\n"
3173 "       color.rgb = diffusetex * Color_Ambient;\n"
3174 "#endif // MODE_FLATCOLOR\n"
3175 "\n"
3176 "\n"
3177 "\n"
3178 "\n"
3179 "#ifdef SHADING\n"
3180 "# ifdef USEDIFFUSE\n"
3181 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3182 "#  ifdef USESPECULAR\n"
3183 "#   ifdef USEEXACTSPECULARMATH\n"
3184 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3185 "#   else\n"
3186 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3187 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3188 "#   endif\n"
3189 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3190 "#  else\n"
3191 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3192 "#  endif\n"
3193 "# else\n"
3194 "       color.rgb = diffusetex * Color_Ambient;\n"
3195 "# endif\n"
3196 "#endif\n"
3197 "\n"
3198 "#ifdef USESHADOWMAPORTHO\n"
3199 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3200 "#endif\n"
3201 "\n"
3202 "#ifdef USEDEFERREDLIGHTMAP\n"
3203 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3204 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3205 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3206 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3207 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3208 "#endif\n"
3209 "\n"
3210 "#ifdef USEGLOW\n"
3211 "#ifdef USEVERTEXTEXTUREBLEND\n"
3212 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3213 "#else\n"
3214 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3215 "#endif\n"
3216 "#endif\n"
3217 "\n"
3218 "#ifdef USEFOG\n"
3219 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3220 "#endif\n"
3221 "\n"
3222 "       // 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"
3223 "#ifdef USEREFLECTION\n"
3224 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3225 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3226 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3227 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3228 "       // FIXME temporary hack to detect the case that the reflection\n"
3229 "       // gets blackened at edges due to leaving the area that contains actual\n"
3230 "       // content.\n"
3231 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3232 "       // 'appening.\n"
3233 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3234 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3235 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3236 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3237 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3238 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3239 "#endif\n"
3240 "\n"
3241 "       gl_FragColor = float4(color);\n"
3242 "}\n"
3243 "#endif // FRAGMENT_SHADER\n"
3244 "\n"
3245 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3246 "#endif // !MODE_DEFERREDGEOMETRY\n"
3247 "#endif // !MODE_WATER\n"
3248 "#endif // !MODE_REFRACTION\n"
3249 "#endif // !MODE_BLOOMBLUR\n"
3250 "#endif // !MODE_GENERIC\n"
3251 "#endif // !MODE_POSTPROCESS\n"
3252 "#endif // !MODE_SHOWDEPTH\n"
3253 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3254 ;
3255
3256 char *glslshaderstring = NULL;
3257 char *cgshaderstring = NULL;
3258 char *hlslshaderstring = NULL;
3259
3260 //=======================================================================================================================================================
3261
3262 typedef struct shaderpermutationinfo_s
3263 {
3264         const char *pretext;
3265         const char *name;
3266 }
3267 shaderpermutationinfo_t;
3268
3269 typedef struct shadermodeinfo_s
3270 {
3271         const char *vertexfilename;
3272         const char *geometryfilename;
3273         const char *fragmentfilename;
3274         const char *pretext;
3275         const char *name;
3276 }
3277 shadermodeinfo_t;
3278
3279 typedef enum shaderpermutation_e
3280 {
3281         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3282         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3283         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3284         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3285         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3286         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3287         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3288         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3289         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3290         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3291         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3292         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3293         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3294         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3295         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3296         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3297         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3298         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3299         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3300         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3301         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3302         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3303         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3304         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3305         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3306         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3307         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3308         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3309         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3310 }
3311 shaderpermutation_t;
3312
3313 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3314 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3315 {
3316         {"#define USEDIFFUSE\n", " diffuse"},
3317         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3318         {"#define USEVIEWTINT\n", " viewtint"},
3319         {"#define USECOLORMAPPING\n", " colormapping"},
3320         {"#define USESATURATION\n", " saturation"},
3321         {"#define USEFOGINSIDE\n", " foginside"},
3322         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3323         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3324         {"#define USEGAMMARAMPS\n", " gammaramps"},
3325         {"#define USECUBEFILTER\n", " cubefilter"},
3326         {"#define USEGLOW\n", " glow"},
3327         {"#define USEBLOOM\n", " bloom"},
3328         {"#define USESPECULAR\n", " specular"},
3329         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3330         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3331         {"#define USEREFLECTION\n", " reflection"},
3332         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3333         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3334         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3335         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3336         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3337         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3338         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3339         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3340         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3341         {"#define USEALPHAKILL\n", " alphakill"},
3342         {"#define USEREFLECTCUBE\n", " reflectcube"},
3343 };
3344
3345 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3346 typedef enum shadermode_e
3347 {
3348         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3349         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3350         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3351         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3352         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3353         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3354         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3355         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3356         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3357         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3358         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3359         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3360         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3361         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3362         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3363         SHADERMODE_COUNT
3364 }
3365 shadermode_t;
3366
3367 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3368 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3369 {
3370         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3371         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3372         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3373         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3374         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3375         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3376         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3377         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3378         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3379         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3380         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3381         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3382         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3383         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3384         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3385 };
3386
3387 #ifdef SUPPORTCG
3388 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3389 {
3390         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3391         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3392         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3393         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3394         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3395         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3396         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3397         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3398         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3399         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3400         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3401         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3402         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3403         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3404         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3405 };
3406 #endif
3407
3408 #ifdef SUPPORTD3D
3409 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3410 {
3411         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3412         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3413         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3414         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3415         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3416         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3417         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3419         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3420         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3421         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3422         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3423         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3426 };
3427 #endif
3428
3429 struct r_glsl_permutation_s;
3430 typedef struct r_glsl_permutation_s
3431 {
3432         /// hash lookup data
3433         struct r_glsl_permutation_s *hashnext;
3434         unsigned int mode;
3435         unsigned int permutation;
3436
3437         /// indicates if we have tried compiling this permutation already
3438         qboolean compiled;
3439         /// 0 if compilation failed
3440         int program;
3441         /// locations of detected uniforms in program object, or -1 if not found
3442         int loc_Texture_First;
3443         int loc_Texture_Second;
3444         int loc_Texture_GammaRamps;
3445         int loc_Texture_Normal;
3446         int loc_Texture_Color;
3447         int loc_Texture_Gloss;
3448         int loc_Texture_Glow;
3449         int loc_Texture_SecondaryNormal;
3450         int loc_Texture_SecondaryColor;
3451         int loc_Texture_SecondaryGloss;
3452         int loc_Texture_SecondaryGlow;
3453         int loc_Texture_Pants;
3454         int loc_Texture_Shirt;
3455         int loc_Texture_FogHeightTexture;
3456         int loc_Texture_FogMask;
3457         int loc_Texture_Lightmap;
3458         int loc_Texture_Deluxemap;
3459         int loc_Texture_Attenuation;
3460         int loc_Texture_Cube;
3461         int loc_Texture_Refraction;
3462         int loc_Texture_Reflection;
3463         int loc_Texture_ShadowMap2D;
3464         int loc_Texture_CubeProjection;
3465         int loc_Texture_ScreenDepth;
3466         int loc_Texture_ScreenNormalMap;
3467         int loc_Texture_ScreenDiffuse;
3468         int loc_Texture_ScreenSpecular;
3469         int loc_Texture_ReflectMask;
3470         int loc_Texture_ReflectCube;
3471         int loc_Alpha;
3472         int loc_BloomBlur_Parameters;
3473         int loc_ClientTime;
3474         int loc_Color_Ambient;
3475         int loc_Color_Diffuse;
3476         int loc_Color_Specular;
3477         int loc_Color_Glow;
3478         int loc_Color_Pants;
3479         int loc_Color_Shirt;
3480         int loc_DeferredColor_Ambient;
3481         int loc_DeferredColor_Diffuse;
3482         int loc_DeferredColor_Specular;
3483         int loc_DeferredMod_Diffuse;
3484         int loc_DeferredMod_Specular;
3485         int loc_DistortScaleRefractReflect;
3486         int loc_EyePosition;
3487         int loc_FogColor;
3488         int loc_FogHeightFade;
3489         int loc_FogPlane;
3490         int loc_FogPlaneViewDist;
3491         int loc_FogRangeRecip;
3492         int loc_LightColor;
3493         int loc_LightDir;
3494         int loc_LightPosition;
3495         int loc_OffsetMapping_Scale;
3496         int loc_PixelSize;
3497         int loc_ReflectColor;
3498         int loc_ReflectFactor;
3499         int loc_ReflectOffset;
3500         int loc_RefractColor;
3501         int loc_Saturation;
3502         int loc_ScreenCenterRefractReflect;
3503         int loc_ScreenScaleRefractReflect;
3504         int loc_ScreenToDepth;
3505         int loc_ShadowMap_Parameters;
3506         int loc_ShadowMap_TextureScale;
3507         int loc_SpecularPower;
3508         int loc_UserVec1;
3509         int loc_UserVec2;
3510         int loc_UserVec3;
3511         int loc_UserVec4;
3512         int loc_ViewTintColor;
3513         int loc_ViewToLight;
3514         int loc_ModelToLight;
3515         int loc_TexMatrix;
3516         int loc_BackgroundTexMatrix;
3517         int loc_ModelViewProjectionMatrix;
3518         int loc_ModelViewMatrix;
3519         int loc_PixelToScreenTexCoord;
3520         int loc_ModelToReflectCube;
3521         int loc_ShadowMapMatrix;
3522         int loc_BloomColorSubtract;
3523 }
3524 r_glsl_permutation_t;
3525
3526 #define SHADERPERMUTATION_HASHSIZE 256
3527
3528 /// information about each possible shader permutation
3529 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3530 /// currently selected permutation
3531 r_glsl_permutation_t *r_glsl_permutation;
3532 /// storage for permutations linked in the hash table
3533 memexpandablearray_t r_glsl_permutationarray;
3534
3535 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3536 {
3537         //unsigned int hashdepth = 0;
3538         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3539         r_glsl_permutation_t *p;
3540         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3541         {
3542                 if (p->mode == mode && p->permutation == permutation)
3543                 {
3544                         //if (hashdepth > 10)
3545                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3546                         return p;
3547                 }
3548                 //hashdepth++;
3549         }
3550         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3551         p->mode = mode;
3552         p->permutation = permutation;
3553         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3554         r_glsl_permutationhash[mode][hashindex] = p;
3555         //if (hashdepth > 10)
3556         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3557         return p;
3558 }
3559
3560 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3561 {
3562         char *shaderstring;
3563         if (!filename || !filename[0])
3564                 return NULL;
3565         if (!strcmp(filename, "glsl/default.glsl"))
3566         {
3567                 if (!glslshaderstring)
3568                 {
3569                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3570                         if (glslshaderstring)
3571                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3572                         else
3573                                 glslshaderstring = (char *)builtinshaderstring;
3574                 }
3575                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3576                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3577                 return shaderstring;
3578         }
3579         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3580         if (shaderstring)
3581         {
3582                 if (printfromdisknotice)
3583                         Con_DPrintf("from disk %s... ", filename);
3584                 return shaderstring;
3585         }
3586         return shaderstring;
3587 }
3588
3589 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3590 {
3591         int i;
3592         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3593         int vertstrings_count = 0;
3594         int geomstrings_count = 0;
3595         int fragstrings_count = 0;
3596         char *vertexstring, *geometrystring, *fragmentstring;
3597         const char *vertstrings_list[32+3];
3598         const char *geomstrings_list[32+3];
3599         const char *fragstrings_list[32+3];
3600         char permutationname[256];
3601
3602         if (p->compiled)
3603                 return;
3604         p->compiled = true;
3605         p->program = 0;
3606
3607         permutationname[0] = 0;
3608         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3609         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3610         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3611
3612         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3613
3614         // the first pretext is which type of shader to compile as
3615         // (later these will all be bound together as a program object)
3616         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3617         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3618         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3619
3620         // the second pretext is the mode (for example a light source)
3621         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3622         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3623         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3624         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3625
3626         // now add all the permutation pretexts
3627         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3628         {
3629                 if (permutation & (1<<i))
3630                 {
3631                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3632                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3633                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3634                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3635                 }
3636                 else
3637                 {
3638                         // keep line numbers correct
3639                         vertstrings_list[vertstrings_count++] = "\n";
3640                         geomstrings_list[geomstrings_count++] = "\n";
3641                         fragstrings_list[fragstrings_count++] = "\n";
3642                 }
3643         }
3644
3645         // now append the shader text itself
3646         vertstrings_list[vertstrings_count++] = vertexstring;
3647         geomstrings_list[geomstrings_count++] = geometrystring;
3648         fragstrings_list[fragstrings_count++] = fragmentstring;
3649
3650         // if any sources were NULL, clear the respective list
3651         if (!vertexstring)
3652                 vertstrings_count = 0;
3653         if (!geometrystring)
3654                 geomstrings_count = 0;
3655         if (!fragmentstring)
3656                 fragstrings_count = 0;
3657
3658         // compile the shader program
3659         if (vertstrings_count + geomstrings_count + fragstrings_count)
3660                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3661         if (p->program)
3662         {
3663                 CHECKGLERROR
3664                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3665                 // look up all the uniform variable names we care about, so we don't
3666                 // have to look them up every time we set them
3667
3668                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3669                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3670                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3671                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3672                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3673                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3674                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3675                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3676                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3677                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3678                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3679                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3680                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3681                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3682                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3683                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3684                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3685                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3686                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3687                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3688                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3689                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3690                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3691                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3692                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3693                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3694                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3695                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3696                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3697                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3698                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3699                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3700                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3701                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3702                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3703                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3704                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3705                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3706                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3707                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3708                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3709                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3710                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3711                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3712                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3713                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3714                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3715                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3716                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3717                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3718                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3719                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3720                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3721                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3722                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3723                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3724                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3725                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3726                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3727                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3728                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3729                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3730                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3731                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3732                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3733                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3734                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3735                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3736                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3737                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3738                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3739                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3740                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3741                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3742                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3743                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3744                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3745                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3746                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3747                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3748                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3749                 // initialize the samplers to refer to the texture units we use
3750                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3751                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3752                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3753                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3754                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3755                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3756                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3757                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3758                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3759                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3760                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3761                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3762                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3763                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3764                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3765                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3766                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3767                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3768                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3769                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3770                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3771                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3772                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3773                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3774                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3775                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3776                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3777                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3778                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3779                 CHECKGLERROR
3780                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3781         }
3782         else
3783                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3784
3785         // free the strings
3786         if (vertexstring)
3787                 Mem_Free(vertexstring);
3788         if (geometrystring)
3789                 Mem_Free(geometrystring);
3790         if (fragmentstring)
3791                 Mem_Free(fragmentstring);
3792 }
3793
3794 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3795 {
3796         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3797         if (r_glsl_permutation != perm)
3798         {
3799                 r_glsl_permutation = perm;
3800                 if (!r_glsl_permutation->program)
3801                 {
3802                         if (!r_glsl_permutation->compiled)
3803                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3804                         if (!r_glsl_permutation->program)
3805                         {
3806                                 // remove features until we find a valid permutation
3807                                 int i;
3808                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3809                                 {
3810                                         // reduce i more quickly whenever it would not remove any bits
3811                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3812                                         if (!(permutation & j))
3813                                                 continue;
3814                                         permutation -= j;
3815                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3816                                         if (!r_glsl_permutation->compiled)
3817                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3818                                         if (r_glsl_permutation->program)
3819                                                 break;
3820                                 }
3821                                 if (i >= SHADERPERMUTATION_COUNT)
3822                                 {
3823                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3824                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3825                                         qglUseProgramObjectARB(0);CHECKGLERROR
3826                                         return; // no bit left to clear, entire mode is broken
3827                                 }
3828                         }
3829                 }
3830                 CHECKGLERROR
3831                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3832         }
3833         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3834         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3835         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3836 }
3837
3838 #ifdef SUPPORTCG
3839 #include <Cg/cgGL.h>
3840 struct r_cg_permutation_s;
3841 typedef struct r_cg_permutation_s
3842 {
3843         /// hash lookup data
3844         struct r_cg_permutation_s *hashnext;
3845         unsigned int mode;
3846         unsigned int permutation;
3847
3848         /// indicates if we have tried compiling this permutation already
3849         qboolean compiled;
3850         /// 0 if compilation failed
3851         CGprogram vprogram;
3852         CGprogram fprogram;
3853         /// locations of detected parameters in programs, or NULL if not found
3854         CGparameter vp_EyePosition;
3855         CGparameter vp_FogPlane;
3856         CGparameter vp_LightDir;
3857         CGparameter vp_LightPosition;
3858         CGparameter vp_ModelToLight;
3859         CGparameter vp_TexMatrix;
3860         CGparameter vp_BackgroundTexMatrix;
3861         CGparameter vp_ModelViewProjectionMatrix;
3862         CGparameter vp_ModelViewMatrix;
3863         CGparameter vp_ShadowMapMatrix;
3864
3865         CGparameter fp_Texture_First;
3866         CGparameter fp_Texture_Second;
3867         CGparameter fp_Texture_GammaRamps;
3868         CGparameter fp_Texture_Normal;
3869         CGparameter fp_Texture_Color;
3870         CGparameter fp_Texture_Gloss;
3871         CGparameter fp_Texture_Glow;
3872         CGparameter fp_Texture_SecondaryNormal;
3873         CGparameter fp_Texture_SecondaryColor;
3874         CGparameter fp_Texture_SecondaryGloss;
3875         CGparameter fp_Texture_SecondaryGlow;
3876         CGparameter fp_Texture_Pants;
3877         CGparameter fp_Texture_Shirt;
3878         CGparameter fp_Texture_FogHeightTexture;
3879         CGparameter fp_Texture_FogMask;
3880         CGparameter fp_Texture_Lightmap;
3881         CGparameter fp_Texture_Deluxemap;
3882         CGparameter fp_Texture_Attenuation;
3883         CGparameter fp_Texture_Cube;
3884         CGparameter fp_Texture_Refraction;
3885         CGparameter fp_Texture_Reflection;
3886         CGparameter fp_Texture_ShadowMap2D;
3887         CGparameter fp_Texture_CubeProjection;
3888         CGparameter fp_Texture_ScreenDepth;
3889         CGparameter fp_Texture_ScreenNormalMap;
3890         CGparameter fp_Texture_ScreenDiffuse;
3891         CGparameter fp_Texture_ScreenSpecular;
3892         CGparameter fp_Texture_ReflectMask;
3893         CGparameter fp_Texture_ReflectCube;
3894         CGparameter fp_Alpha;
3895         CGparameter fp_BloomBlur_Parameters;
3896         CGparameter fp_ClientTime;
3897         CGparameter fp_Color_Ambient;
3898         CGparameter fp_Color_Diffuse;
3899         CGparameter fp_Color_Specular;
3900         CGparameter fp_Color_Glow;
3901         CGparameter fp_Color_Pants;
3902         CGparameter fp_Color_Shirt;
3903         CGparameter fp_DeferredColor_Ambient;
3904         CGparameter fp_DeferredColor_Diffuse;
3905         CGparameter fp_DeferredColor_Specular;
3906         CGparameter fp_DeferredMod_Diffuse;
3907         CGparameter fp_DeferredMod_Specular;
3908         CGparameter fp_DistortScaleRefractReflect;
3909         CGparameter fp_EyePosition;
3910         CGparameter fp_FogColor;
3911         CGparameter fp_FogHeightFade;
3912         CGparameter fp_FogPlane;
3913         CGparameter fp_FogPlaneViewDist;
3914         CGparameter fp_FogRangeRecip;
3915         CGparameter fp_LightColor;
3916         CGparameter fp_LightDir;
3917         CGparameter fp_LightPosition;
3918         CGparameter fp_OffsetMapping_Scale;
3919         CGparameter fp_PixelSize;
3920         CGparameter fp_ReflectColor;
3921         CGparameter fp_ReflectFactor;
3922         CGparameter fp_ReflectOffset;
3923         CGparameter fp_RefractColor;
3924         CGparameter fp_Saturation;
3925         CGparameter fp_ScreenCenterRefractReflect;
3926         CGparameter fp_ScreenScaleRefractReflect;
3927         CGparameter fp_ScreenToDepth;
3928         CGparameter fp_ShadowMap_Parameters;
3929         CGparameter fp_ShadowMap_TextureScale;
3930         CGparameter fp_SpecularPower;
3931         CGparameter fp_UserVec1;
3932         CGparameter fp_UserVec2;
3933         CGparameter fp_UserVec3;
3934         CGparameter fp_UserVec4;
3935         CGparameter fp_ViewTintColor;
3936         CGparameter fp_ViewToLight;
3937         CGparameter fp_PixelToScreenTexCoord;
3938         CGparameter fp_ModelToReflectCube;
3939         CGparameter fp_BloomColorSubtract;
3940 }
3941 r_cg_permutation_t;
3942
3943 /// information about each possible shader permutation
3944 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3945 /// currently selected permutation
3946 r_cg_permutation_t *r_cg_permutation;
3947 /// storage for permutations linked in the hash table
3948 memexpandablearray_t r_cg_permutationarray;
3949
3950 #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));}}
3951
3952 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3953 {
3954         //unsigned int hashdepth = 0;
3955         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3956         r_cg_permutation_t *p;
3957         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3958         {
3959                 if (p->mode == mode && p->permutation == permutation)
3960                 {
3961                         //if (hashdepth > 10)
3962                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3963                         return p;
3964                 }
3965                 //hashdepth++;
3966         }
3967         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3968         p->mode = mode;
3969         p->permutation = permutation;
3970         p->hashnext = r_cg_permutationhash[mode][hashindex];
3971         r_cg_permutationhash[mode][hashindex] = p;
3972         //if (hashdepth > 10)
3973         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3974         return p;
3975 }
3976
3977 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3978 {
3979         char *shaderstring;
3980         if (!filename || !filename[0])
3981                 return NULL;
3982         if (!strcmp(filename, "cg/default.cg"))
3983         {
3984                 if (!cgshaderstring)
3985                 {
3986                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3987                         if (cgshaderstring)
3988                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3989                         else
3990                                 cgshaderstring = (char *)builtincgshaderstring;
3991                 }
3992                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3993                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3994                 return shaderstring;
3995         }
3996         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3997         if (shaderstring)
3998         {
3999                 if (printfromdisknotice)
4000                         Con_DPrintf("from disk %s... ", filename);
4001                 return shaderstring;
4002         }
4003         return shaderstring;
4004 }
4005
4006 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4007 {
4008         // TODO: load or create .fp and .vp shader files
4009 }
4010
4011 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4012 {
4013         int i;
4014         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4015         int vertstrings_count = 0, vertstring_length = 0;
4016         int geomstrings_count = 0, geomstring_length = 0;
4017         int fragstrings_count = 0, fragstring_length = 0;
4018         char *t;
4019         char *vertexstring, *geometrystring, *fragmentstring;
4020         char *vertstring, *geomstring, *fragstring;
4021         const char *vertstrings_list[32+3];
4022         const char *geomstrings_list[32+3];
4023         const char *fragstrings_list[32+3];
4024         char permutationname[256];
4025         char cachename[256];
4026         CGprofile vertexProfile;
4027         CGprofile fragmentProfile;
4028
4029         if (p->compiled)
4030                 return;
4031         p->compiled = true;
4032         p->vprogram = NULL;
4033         p->fprogram = NULL;
4034
4035         permutationname[0] = 0;
4036         cachename[0] = 0;
4037         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4038         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4039         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4040
4041         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4042         strlcat(cachename, "cg/", sizeof(cachename));
4043
4044         // the first pretext is which type of shader to compile as
4045         // (later these will all be bound together as a program object)
4046         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4047         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4048         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4049
4050         // the second pretext is the mode (for example a light source)
4051         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4052         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4053         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4054         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4055         strlcat(cachename, modeinfo->name, sizeof(cachename));
4056
4057         // now add all the permutation pretexts
4058         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4059         {
4060                 if (permutation & (1<<i))
4061                 {
4062                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4063                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4064                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4065                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4066                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4067                 }
4068                 else
4069                 {
4070                         // keep line numbers correct
4071                         vertstrings_list[vertstrings_count++] = "\n";
4072                         geomstrings_list[geomstrings_count++] = "\n";
4073                         fragstrings_list[fragstrings_count++] = "\n";
4074                 }
4075         }
4076
4077         // replace spaces in the cachename with _ characters
4078         for (i = 0;cachename[i];i++)
4079                 if (cachename[i] == ' ')
4080                         cachename[i] = '_';
4081
4082         // now append the shader text itself
4083         vertstrings_list[vertstrings_count++] = vertexstring;
4084         geomstrings_list[geomstrings_count++] = geometrystring;
4085         fragstrings_list[fragstrings_count++] = fragmentstring;
4086
4087         // if any sources were NULL, clear the respective list
4088         if (!vertexstring)
4089                 vertstrings_count = 0;
4090         if (!geometrystring)
4091                 geomstrings_count = 0;
4092         if (!fragmentstring)
4093                 fragstrings_count = 0;
4094
4095         vertstring_length = 0;
4096         for (i = 0;i < vertstrings_count;i++)
4097                 vertstring_length += strlen(vertstrings_list[i]);
4098         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4099         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4100                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4101
4102         geomstring_length = 0;
4103         for (i = 0;i < geomstrings_count;i++)
4104                 geomstring_length += strlen(geomstrings_list[i]);
4105         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4106         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4107                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4108
4109         fragstring_length = 0;
4110         for (i = 0;i < fragstrings_count;i++)
4111                 fragstring_length += strlen(fragstrings_list[i]);
4112         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4113         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4114                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4115
4116         CHECKGLERROR
4117         CHECKCGERROR
4118         //vertexProfile = CG_PROFILE_ARBVP1;
4119         //fragmentProfile = CG_PROFILE_ARBFP1;
4120         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4121         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4122         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4123         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4124         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4125         CHECKGLERROR
4126
4127         // try to load the cached shader, or generate one
4128         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4129
4130         // if caching failed, do a dynamic compile for now
4131         CHECKCGERROR
4132         if (vertstring[0] && !p->vprogram)
4133                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4134         CHECKCGERROR
4135         if (fragstring[0] && !p->fprogram)
4136                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4137         CHECKCGERROR
4138
4139         // look up all the uniform variable names we care about, so we don't
4140         // have to look them up every time we set them
4141         if (p->vprogram)
4142         {
4143                 CHECKCGERROR
4144                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4145                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4146                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4147                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4148                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4149                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4150                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4151                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4152                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4153                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4154                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4155                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4156                 CHECKCGERROR
4157         }
4158         if (p->fprogram)
4159         {
4160                 CHECKCGERROR
4161                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4162                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4163                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4164                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4165                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4166                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4167                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4168                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4169                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4170                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4171                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4172                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4173                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4174                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4175                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4176                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4177                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4178                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4179                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4180                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4181                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4182                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4183                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4184                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4185                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4186                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4187                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4188                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4189                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4190                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4191                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4192                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4193                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4194                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4195                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4196                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4197                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4198                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4199                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4200                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4201                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4202                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4203                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4204                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4205                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4206                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4207                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4208                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4209                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4210                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4211                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4212                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4213                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4214                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4215                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4216                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4217                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4218                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4219                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4220                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4221                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4222                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4223                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4224                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4225                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4226                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4227                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4228                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4229                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4230                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4231                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4232                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4233                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4234                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4235                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4236                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4237                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4238                 CHECKCGERROR
4239         }
4240
4241         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4242                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4243         else
4244                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4245
4246         // free the strings
4247         if (vertstring)
4248                 Mem_Free(vertstring);
4249         if (geomstring)
4250                 Mem_Free(geomstring);
4251         if (fragstring)
4252                 Mem_Free(fragstring);
4253         if (vertexstring)
4254                 Mem_Free(vertexstring);
4255         if (geometrystring)
4256                 Mem_Free(geometrystring);
4257         if (fragmentstring)
4258                 Mem_Free(fragmentstring);
4259 }
4260
4261 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4262 {
4263         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4264         CHECKGLERROR
4265         CHECKCGERROR
4266         if (r_cg_permutation != perm)
4267         {
4268                 r_cg_permutation = perm;
4269                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4270                 {
4271                         if (!r_cg_permutation->compiled)
4272                                 R_CG_CompilePermutation(perm, mode, permutation);
4273                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4274                         {
4275                                 // remove features until we find a valid permutation
4276                                 int i;
4277                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4278                                 {
4279                                         // reduce i more quickly whenever it would not remove any bits
4280                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4281                                         if (!(permutation & j))
4282                                                 continue;
4283                                         permutation -= j;
4284                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4285                                         if (!r_cg_permutation->compiled)
4286                                                 R_CG_CompilePermutation(perm, mode, permutation);
4287                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4288                                                 break;
4289                                 }
4290                                 if (i >= SHADERPERMUTATION_COUNT)
4291                                 {
4292                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4293                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4294                                         return; // no bit left to clear, entire mode is broken
4295                                 }
4296                         }
4297                 }
4298                 CHECKGLERROR
4299                 CHECKCGERROR
4300                 if (r_cg_permutation->vprogram)
4301                 {
4302                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4303                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4304                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4305                 }
4306                 else
4307                 {
4308                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4309                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4310                 }
4311                 if (r_cg_permutation->fprogram)
4312                 {
4313                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4314                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4315                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4316                 }
4317                 else
4318                 {
4319                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4320                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4321                 }
4322         }
4323         CHECKCGERROR
4324         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4325         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4326         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4327 }
4328
4329 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4330 {
4331         cgGLSetTextureParameter(param, R_GetTexture(tex));
4332         cgGLEnableTextureParameter(param);
4333 }
4334 #endif
4335
4336 #ifdef SUPPORTD3D
4337
4338 #ifdef SUPPORTD3D
4339 #include <d3d9.h>
4340 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4341 extern D3DCAPS9 vid_d3d9caps;
4342 #endif
4343
4344 struct r_hlsl_permutation_s;
4345 typedef struct r_hlsl_permutation_s
4346 {
4347         /// hash lookup data
4348         struct r_hlsl_permutation_s *hashnext;
4349         unsigned int mode;
4350         unsigned int permutation;
4351
4352         /// indicates if we have tried compiling this permutation already
4353         qboolean compiled;
4354         /// NULL if compilation failed
4355         IDirect3DVertexShader9 *vertexshader;
4356         IDirect3DPixelShader9 *pixelshader;
4357 }
4358 r_hlsl_permutation_t;
4359
4360 typedef enum D3DVSREGISTER_e
4361 {
4362         D3DVSREGISTER_TexMatrix = 0, // float4x4
4363         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4364         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4365         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4366         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4367         D3DVSREGISTER_ModelToLight = 20, // float4x4
4368         D3DVSREGISTER_EyePosition = 24,
4369         D3DVSREGISTER_FogPlane = 25,
4370         D3DVSREGISTER_LightDir = 26,
4371         D3DVSREGISTER_LightPosition = 27,
4372 }
4373 D3DVSREGISTER_t;
4374
4375 typedef enum D3DPSREGISTER_e
4376 {
4377         D3DPSREGISTER_Alpha = 0,
4378         D3DPSREGISTER_BloomBlur_Parameters = 1,
4379         D3DPSREGISTER_ClientTime = 2,
4380         D3DPSREGISTER_Color_Ambient = 3,
4381         D3DPSREGISTER_Color_Diffuse = 4,
4382         D3DPSREGISTER_Color_Specular = 5,
4383         D3DPSREGISTER_Color_Glow = 6,
4384         D3DPSREGISTER_Color_Pants = 7,
4385         D3DPSREGISTER_Color_Shirt = 8,
4386         D3DPSREGISTER_DeferredColor_Ambient = 9,
4387         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4388         D3DPSREGISTER_DeferredColor_Specular = 11,
4389         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4390         D3DPSREGISTER_DeferredMod_Specular = 13,
4391         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4392         D3DPSREGISTER_EyePosition = 15, // unused
4393         D3DPSREGISTER_FogColor = 16,
4394         D3DPSREGISTER_FogHeightFade = 17,
4395         D3DPSREGISTER_FogPlane = 18,
4396         D3DPSREGISTER_FogPlaneViewDist = 19,
4397         D3DPSREGISTER_FogRangeRecip = 20,
4398         D3DPSREGISTER_LightColor = 21,
4399         D3DPSREGISTER_LightDir = 22, // unused
4400         D3DPSREGISTER_LightPosition = 23,
4401         D3DPSREGISTER_OffsetMapping_Scale = 24,
4402         D3DPSREGISTER_PixelSize = 25,
4403         D3DPSREGISTER_ReflectColor = 26,
4404         D3DPSREGISTER_ReflectFactor = 27,
4405         D3DPSREGISTER_ReflectOffset = 28,
4406         D3DPSREGISTER_RefractColor = 29,
4407         D3DPSREGISTER_Saturation = 30,
4408         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4409         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4410         D3DPSREGISTER_ScreenToDepth = 33,
4411         D3DPSREGISTER_ShadowMap_Parameters = 34,
4412         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4413         D3DPSREGISTER_SpecularPower = 36,
4414         D3DPSREGISTER_UserVec1 = 37,
4415         D3DPSREGISTER_UserVec2 = 38,
4416         D3DPSREGISTER_UserVec3 = 39,
4417         D3DPSREGISTER_UserVec4 = 40,
4418         D3DPSREGISTER_ViewTintColor = 41,
4419         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4420         D3DPSREGISTER_BloomColorSubtract = 43,
4421         D3DPSREGISTER_ViewToLight = 44, // float4x4
4422         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4423         // next at 52
4424 }
4425 D3DPSREGISTER_t;
4426
4427 /// information about each possible shader permutation
4428 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4429 /// currently selected permutation
4430 r_hlsl_permutation_t *r_hlsl_permutation;
4431 /// storage for permutations linked in the hash table
4432 memexpandablearray_t r_hlsl_permutationarray;
4433
4434 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4435 {
4436         //unsigned int hashdepth = 0;
4437         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4438         r_hlsl_permutation_t *p;
4439         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4440         {
4441                 if (p->mode == mode && p->permutation == permutation)
4442                 {
4443                         //if (hashdepth > 10)
4444                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4445                         return p;
4446                 }
4447                 //hashdepth++;
4448         }
4449         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4450         p->mode = mode;
4451         p->permutation = permutation;
4452         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4453         r_hlsl_permutationhash[mode][hashindex] = p;
4454         //if (hashdepth > 10)
4455         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4456         return p;
4457 }
4458
4459 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4460 {
4461         char *shaderstring;
4462         if (!filename || !filename[0])
4463                 return NULL;
4464         if (!strcmp(filename, "hlsl/default.hlsl"))
4465         {
4466                 if (!hlslshaderstring)
4467                 {
4468                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4469                         if (hlslshaderstring)
4470                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4471                         else
4472                                 hlslshaderstring = (char *)builtincgshaderstring;
4473                 }
4474                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4475                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4476                 return shaderstring;
4477         }
4478         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4479         if (shaderstring)
4480         {
4481                 if (printfromdisknotice)
4482                         Con_DPrintf("from disk %s... ", filename);
4483                 return shaderstring;
4484         }
4485         return shaderstring;
4486 }
4487
4488 #include <d3dx9.h>
4489 //#include <d3dx9shader.h>
4490 //#include <d3dx9mesh.h>
4491
4492 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4493 {
4494         DWORD *vsbin = NULL;
4495         DWORD *psbin = NULL;
4496         fs_offset_t vsbinsize;
4497         fs_offset_t psbinsize;
4498 //      IDirect3DVertexShader9 *vs = NULL;
4499 //      IDirect3DPixelShader9 *ps = NULL;
4500         ID3DXBuffer *vslog = NULL;
4501         ID3DXBuffer *vsbuffer = NULL;
4502         ID3DXConstantTable *vsconstanttable = NULL;
4503         ID3DXBuffer *pslog = NULL;
4504         ID3DXBuffer *psbuffer = NULL;
4505         ID3DXConstantTable *psconstanttable = NULL;
4506         int vsresult = 0;
4507         int psresult = 0;
4508         char temp[MAX_INPUTLINE];
4509         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4510         qboolean debugshader = gl_paranoid.integer != 0;
4511         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4512         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4513         if (!debugshader)
4514         {
4515                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4516                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4517         }
4518         if ((!vsbin && vertstring) || (!psbin && fragstring))
4519         {
4520                 const char* dllnames_d3dx9 [] =
4521                 {
4522                         "d3dx9_43.dll",
4523                         "d3dx9_42.dll",
4524                         "d3dx9_41.dll",
4525                         "d3dx9_40.dll",
4526                         "d3dx9_39.dll",
4527                         "d3dx9_38.dll",
4528                         "d3dx9_37.dll",
4529                         "d3dx9_36.dll",
4530                         "d3dx9_35.dll",
4531                         "d3dx9_34.dll",
4532                         "d3dx9_33.dll",
4533                         "d3dx9_32.dll",
4534                         "d3dx9_31.dll",
4535                         "d3dx9_30.dll",
4536                         "d3dx9_29.dll",
4537                         "d3dx9_28.dll",
4538                         "d3dx9_27.dll",
4539                         "d3dx9_26.dll",
4540                         "d3dx9_25.dll",
4541                         "d3dx9_24.dll",
4542                         NULL
4543                 };
4544                 dllhandle_t d3dx9_dll = NULL;
4545                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4546                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4547                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4548                 dllfunction_t d3dx9_dllfuncs[] =
4549                 {
4550                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4551                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4552                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4553                         {NULL, NULL}
4554                 };
4555                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4556                 {
4557                         DWORD shaderflags = 0;
4558                         if (debugshader)
4559                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4560                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4561                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4562                         if (vertstring && vertstring[0])
4563                         {
4564                                 if (debugshader)
4565                                 {
4566 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4567 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4568                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4569                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4570                                 }
4571                                 else
4572                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4573                                 if (vsbuffer)
4574                                 {
4575                                         vsbinsize = vsbuffer->GetBufferSize();
4576                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4577                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4578                                         vsbuffer->Release();
4579                                 }
4580                                 if (vslog)
4581                                 {
4582                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4583                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4584                                         vslog->Release();
4585                                 }
4586                         }
4587                         if (fragstring && fragstring[0])
4588                         {
4589                                 if (debugshader)
4590                                 {
4591 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4592 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4593                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4594                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4595                                 }
4596                                 else
4597                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4598                                 if (psbuffer)
4599                                 {
4600                                         psbinsize = psbuffer->GetBufferSize();
4601                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4602                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4603                                         psbuffer->Release();
4604                                 }
4605                                 if (pslog)
4606                                 {
4607                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4608                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4609                                         pslog->Release();
4610                                 }
4611                         }
4612                         Sys_UnloadLibrary(&d3dx9_dll);
4613                 }
4614                 else
4615                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4616         }
4617         if (vsbin && psbin)
4618         {
4619                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4620                 if (FAILED(vsresult))
4621                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4622                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4623                 if (FAILED(psresult))
4624                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4625         }
4626         // free the shader data
4627         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4628         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4629 }
4630
4631 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4632 {
4633         int i;
4634         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4635         int vertstrings_count = 0, vertstring_length = 0;
4636         int geomstrings_count = 0, geomstring_length = 0;
4637         int fragstrings_count = 0, fragstring_length = 0;
4638         char *t;
4639         char *vertexstring, *geometrystring, *fragmentstring;
4640         char *vertstring, *geomstring, *fragstring;
4641         const char *vertstrings_list[32+3];
4642         const char *geomstrings_list[32+3];
4643         const char *fragstrings_list[32+3];
4644         char permutationname[256];
4645         char cachename[256];
4646
4647         if (p->compiled)
4648                 return;
4649         p->compiled = true;
4650         p->vertexshader = NULL;
4651         p->pixelshader = NULL;
4652
4653         permutationname[0] = 0;
4654         cachename[0] = 0;
4655         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4656         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4657         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4658
4659         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4660         strlcat(cachename, "hlsl/", sizeof(cachename));
4661
4662         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4663         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4664         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4665         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4666
4667         // the first pretext is which type of shader to compile as
4668         // (later these will all be bound together as a program object)
4669         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4670         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4671         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4672
4673         // the second pretext is the mode (for example a light source)
4674         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4675         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4676         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4677         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4678         strlcat(cachename, modeinfo->name, sizeof(cachename));
4679
4680         // now add all the permutation pretexts
4681         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4682         {
4683                 if (permutation & (1<<i))
4684                 {
4685                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4686                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4687                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4688                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4689                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4690                 }
4691                 else
4692                 {
4693                         // keep line numbers correct
4694                         vertstrings_list[vertstrings_count++] = "\n";
4695                         geomstrings_list[geomstrings_count++] = "\n";
4696                         fragstrings_list[fragstrings_count++] = "\n";
4697                 }
4698         }
4699
4700         // replace spaces in the cachename with _ characters
4701         for (i = 0;cachename[i];i++)
4702                 if (cachename[i] == ' ')
4703                         cachename[i] = '_';
4704
4705         // now append the shader text itself
4706         vertstrings_list[vertstrings_count++] = vertexstring;
4707         geomstrings_list[geomstrings_count++] = geometrystring;
4708         fragstrings_list[fragstrings_count++] = fragmentstring;
4709
4710         // if any sources were NULL, clear the respective list
4711         if (!vertexstring)
4712                 vertstrings_count = 0;
4713         if (!geometrystring)
4714                 geomstrings_count = 0;
4715         if (!fragmentstring)
4716                 fragstrings_count = 0;
4717
4718         vertstring_length = 0;
4719         for (i = 0;i < vertstrings_count;i++)
4720                 vertstring_length += strlen(vertstrings_list[i]);
4721         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4722         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4723                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4724
4725         geomstring_length = 0;
4726         for (i = 0;i < geomstrings_count;i++)
4727                 geomstring_length += strlen(geomstrings_list[i]);
4728         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4729         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4730                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4731
4732         fragstring_length = 0;
4733         for (i = 0;i < fragstrings_count;i++)
4734                 fragstring_length += strlen(fragstrings_list[i]);
4735         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4736         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4737                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4738
4739         // try to load the cached shader, or generate one
4740         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4741
4742         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4743                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4744         else
4745                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4746
4747         // free the strings
4748         if (vertstring)
4749                 Mem_Free(vertstring);
4750         if (geomstring)
4751                 Mem_Free(geomstring);
4752         if (fragstring)
4753                 Mem_Free(fragstring);
4754         if (vertexstring)
4755                 Mem_Free(vertexstring);
4756         if (geometrystring)
4757                 Mem_Free(geometrystring);
4758         if (fragmentstring)
4759                 Mem_Free(fragmentstring);
4760 }
4761
4762 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4763 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4764 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);}
4765 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);}
4766 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);}
4767 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);}
4768
4769 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4770 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4771 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);}
4772 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);}
4773 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);}
4774 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);}
4775
4776 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4777 {
4778         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4779         if (r_hlsl_permutation != perm)
4780         {
4781                 r_hlsl_permutation = perm;
4782                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4783                 {
4784                         if (!r_hlsl_permutation->compiled)
4785                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4786                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4787                         {
4788                                 // remove features until we find a valid permutation
4789                                 int i;
4790                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4791                                 {
4792                                         // reduce i more quickly whenever it would not remove any bits
4793                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4794                                         if (!(permutation & j))
4795                                                 continue;
4796                                         permutation -= j;
4797                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4798                                         if (!r_hlsl_permutation->compiled)
4799                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4800                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4801                                                 break;
4802                                 }
4803                                 if (i >= SHADERPERMUTATION_COUNT)
4804                                 {
4805                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4806                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4807                                         return; // no bit left to clear, entire mode is broken
4808                                 }
4809                         }
4810                 }
4811                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4812                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4813         }
4814         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4815         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4816         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4817 }
4818 #endif
4819
4820 void R_GLSL_Restart_f(void)
4821 {
4822         unsigned int i, limit;
4823         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4824                 Mem_Free(glslshaderstring);
4825         glslshaderstring = NULL;
4826         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4827                 Mem_Free(cgshaderstring);
4828         cgshaderstring = NULL;
4829         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4830                 Mem_Free(hlslshaderstring);
4831         hlslshaderstring = NULL;
4832         switch(vid.renderpath)
4833         {
4834         case RENDERPATH_D3D9:
4835 #ifdef SUPPORTD3D
4836                 {
4837                         r_hlsl_permutation_t *p;
4838                         r_hlsl_permutation = NULL;
4839 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4840 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4841 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4842 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4843                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4844                         for (i = 0;i < limit;i++)
4845                         {
4846                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4847                                 {
4848                                         if (p->vertexshader)
4849                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4850                                         if (p->pixelshader)
4851                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4852                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4853                                 }
4854                         }
4855                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4856                 }
4857 #endif
4858                 break;
4859         case RENDERPATH_D3D10:
4860                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4861                 break;
4862         case RENDERPATH_D3D11:
4863                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4864                 break;
4865         case RENDERPATH_GL20:
4866                 {
4867                         r_glsl_permutation_t *p;
4868                         r_glsl_permutation = NULL;
4869                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4870                         for (i = 0;i < limit;i++)
4871                         {
4872                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4873                                 {
4874                                         GL_Backend_FreeProgram(p->program);
4875                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4876                                 }
4877                         }
4878                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4879                 }
4880                 break;
4881         case RENDERPATH_CGGL:
4882 #ifdef SUPPORTCG
4883                 {
4884                         r_cg_permutation_t *p;
4885                         r_cg_permutation = NULL;
4886                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4887                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4888                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4889                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4890                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4891                         for (i = 0;i < limit;i++)
4892                         {
4893                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4894                                 {
4895                                         if (p->vprogram)
4896                                                 cgDestroyProgram(p->vprogram);
4897                                         if (p->fprogram)
4898                                                 cgDestroyProgram(p->fprogram);
4899                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4900                                 }
4901                         }
4902                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4903                 }
4904 #endif
4905                 break;
4906         case RENDERPATH_GL13:
4907         case RENDERPATH_GL11:
4908                 break;
4909         }
4910 }
4911
4912 void R_GLSL_DumpShader_f(void)
4913 {
4914         int i;
4915         qfile_t *file;
4916
4917         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4918         if (file)
4919         {
4920                 FS_Print(file, "/* The engine may define the following macros:\n");
4921                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4922                 for (i = 0;i < SHADERMODE_COUNT;i++)
4923                         FS_Print(file, glslshadermodeinfo[i].pretext);
4924                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4925                         FS_Print(file, shaderpermutationinfo[i].pretext);
4926                 FS_Print(file, "*/\n");
4927                 FS_Print(file, builtinshaderstring);
4928                 FS_Close(file);
4929                 Con_Printf("glsl/default.glsl written\n");
4930         }
4931         else
4932                 Con_Printf("failed to write to glsl/default.glsl\n");
4933
4934 #ifdef SUPPORTCG
4935         file = FS_OpenRealFile("cg/default.cg", "w", false);
4936         if (file)
4937         {
4938                 FS_Print(file, "/* The engine may define the following macros:\n");
4939                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4940                 for (i = 0;i < SHADERMODE_COUNT;i++)
4941                         FS_Print(file, cgshadermodeinfo[i].pretext);
4942                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4943                         FS_Print(file, shaderpermutationinfo[i].pretext);
4944                 FS_Print(file, "*/\n");
4945                 FS_Print(file, builtincgshaderstring);
4946                 FS_Close(file);
4947                 Con_Printf("cg/default.cg written\n");
4948         }
4949         else
4950                 Con_Printf("failed to write to cg/default.cg\n");
4951 #endif
4952
4953 #ifdef SUPPORTD3D
4954         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4955         if (file)
4956         {
4957                 FS_Print(file, "/* The engine may define the following macros:\n");
4958                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4959                 for (i = 0;i < SHADERMODE_COUNT;i++)
4960                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4961                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4962                         FS_Print(file, shaderpermutationinfo[i].pretext);
4963                 FS_Print(file, "*/\n");
4964                 FS_Print(file, builtincgshaderstring);
4965                 FS_Close(file);
4966                 Con_Printf("hlsl/default.hlsl written\n");
4967         }
4968         else
4969                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4970 #endif
4971 }
4972
4973 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4974 {
4975         if (!second)
4976                 texturemode = GL_MODULATE;
4977         switch (vid.renderpath)
4978         {
4979         case RENDERPATH_D3D9:
4980 #ifdef SUPPORTD3D
4981                 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))));
4982                 R_Mesh_TexBind(GL20TU_FIRST , first );
4983                 R_Mesh_TexBind(GL20TU_SECOND, second);
4984 #endif
4985                 break;
4986         case RENDERPATH_D3D10:
4987                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4988                 break;
4989         case RENDERPATH_D3D11:
4990                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4991                 break;
4992         case RENDERPATH_GL20:
4993                 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))));
4994                 R_Mesh_TexBind(GL20TU_FIRST , first );
4995                 R_Mesh_TexBind(GL20TU_SECOND, second);
4996                 break;
4997         case RENDERPATH_CGGL:
4998 #ifdef SUPPORTCG
4999                 CHECKCGERROR
5000                 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))));
5001                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5002                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5003 #endif
5004                 break;
5005         case RENDERPATH_GL13:
5006                 R_Mesh_TexBind(0, first );
5007                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5008                 R_Mesh_TexBind(1, second);
5009                 if (second)
5010                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5011                 break;
5012         case RENDERPATH_GL11:
5013                 R_Mesh_TexBind(0, first );
5014                 break;
5015         }
5016 }
5017
5018 void R_SetupShader_DepthOrShadow(void)
5019 {
5020         switch (vid.renderpath)
5021         {
5022         case RENDERPATH_D3D9:
5023 #ifdef SUPPORTD3D
5024                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5025 #endif
5026                 break;
5027         case RENDERPATH_D3D10:
5028                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5029                 break;
5030         case RENDERPATH_D3D11:
5031                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5032                 break;
5033         case RENDERPATH_GL20:
5034                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5035                 break;
5036         case RENDERPATH_CGGL:
5037 #ifdef SUPPORTCG
5038                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5039 #endif
5040                 break;
5041         case RENDERPATH_GL13:
5042                 R_Mesh_TexBind(0, 0);
5043                 R_Mesh_TexBind(1, 0);
5044                 break;
5045         case RENDERPATH_GL11:
5046                 R_Mesh_TexBind(0, 0);
5047                 break;
5048         }
5049 }
5050
5051 void R_SetupShader_ShowDepth(void)
5052 {
5053         switch (vid.renderpath)
5054         {
5055         case RENDERPATH_D3D9:
5056 #ifdef SUPPORTHLSL
5057                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5058 #endif
5059                 break;
5060         case RENDERPATH_D3D10:
5061                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5062                 break;
5063         case RENDERPATH_D3D11:
5064                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5065                 break;
5066         case RENDERPATH_GL20:
5067                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5068                 break;
5069         case RENDERPATH_CGGL:
5070 #ifdef SUPPORTCG
5071                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5072 #endif
5073                 break;
5074         case RENDERPATH_GL13:
5075                 break;
5076         case RENDERPATH_GL11:
5077                 break;
5078         }
5079 }
5080
5081 extern qboolean r_shadow_usingdeferredprepass;
5082 extern cvar_t r_shadow_deferred_8bitrange;
5083 extern rtexture_t *r_shadow_attenuationgradienttexture;
5084 extern rtexture_t *r_shadow_attenuation2dtexture;
5085 extern rtexture_t *r_shadow_attenuation3dtexture;
5086 extern qboolean r_shadow_usingshadowmap2d;
5087 extern qboolean r_shadow_usingshadowmaportho;
5088 extern float r_shadow_shadowmap_texturescale[2];
5089 extern float r_shadow_shadowmap_parameters[4];
5090 extern qboolean r_shadow_shadowmapvsdct;
5091 extern qboolean r_shadow_shadowmapsampler;
5092 extern int r_shadow_shadowmappcf;
5093 extern rtexture_t *r_shadow_shadowmap2dtexture;
5094 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5095 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5096 extern matrix4x4_t r_shadow_shadowmapmatrix;
5097 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5098 extern int r_shadow_prepass_width;
5099 extern int r_shadow_prepass_height;
5100 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5101 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5102 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5103 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5104 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5105 extern cvar_t gl_mesh_separatearrays;
5106 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5107 {
5108         // a blendfunc allows colormod if:
5109         // a) it can never keep the destination pixel invariant, or
5110         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5111         // this is to prevent unintended side effects from colormod
5112
5113         // in formulas:
5114         // IF there is a (s, sa) for which for all (d, da),
5115         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5116         // THEN, for this (s, sa) and all (colormod, d, da):
5117         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5118         // OBVIOUSLY, this means that
5119         //   s*colormod * src(s*colormod, d, sa, da) = 0
5120         //   dst(s*colormod, d, sa, da)              = 1
5121
5122         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5123
5124         // main condition to leave dst color invariant:
5125         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5126         //   src == GL_ZERO:
5127         //     s * 0 + d * dst(s, d, sa, da) == d
5128         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5129         //       => colormod is a problem for GL_SRC_COLOR only
5130         //   src == GL_ONE:
5131         //     s + d * dst(s, d, sa, da) == d
5132         //       => s == 0
5133         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5134         //       => colormod is never problematic for these
5135         //   src == GL_SRC_COLOR:
5136         //     s*s + d * dst(s, d, sa, da) == d
5137         //       => s == 0
5138         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5139         //       => colormod is never problematic for these
5140         //   src == GL_ONE_MINUS_SRC_COLOR:
5141         //     s*(1-s) + d * dst(s, d, sa, da) == d
5142         //       => s == 0 or s == 1
5143         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5144         //       => colormod is a problem for GL_SRC_COLOR only
5145         //   src == GL_DST_COLOR
5146         //     s*d + d * dst(s, d, sa, da) == d
5147         //       => s == 1
5148         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5149         //       => colormod is always a problem
5150         //     or
5151         //       => s == 0
5152         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5153         //       => colormod is never problematic for these
5154         //       => BUT, we do not know s! We must assume it is problematic
5155         //       then... except in GL_ONE case, where we know all invariant
5156         //       cases are fine
5157         //   src == GL_ONE_MINUS_DST_COLOR
5158         //     s*(1-d) + d * dst(s, d, sa, da) == d
5159         //       => s == 0 (1-d is impossible to handle for our desired result)
5160         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5161         //       => colormod is never problematic for these
5162         //   src == GL_SRC_ALPHA
5163         //     s*sa + d * dst(s, d, sa, da) == d
5164         //       => s == 0, or sa == 0
5165         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5166         //       => colormod breaks in the case GL_SRC_COLOR only
5167         //   src == GL_ONE_MINUS_SRC_ALPHA
5168         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5169         //       => s == 0, or sa == 1
5170         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5171         //       => colormod breaks in the case GL_SRC_COLOR only
5172         //   src == GL_DST_ALPHA
5173         //     s*da + d * dst(s, d, sa, da) == d
5174         //       => s == 0
5175         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5176         //       => colormod is never problematic for these
5177
5178         switch(src)
5179         {
5180                 case GL_ZERO:
5181                 case GL_ONE_MINUS_SRC_COLOR:
5182                 case GL_SRC_ALPHA:
5183                 case GL_ONE_MINUS_SRC_ALPHA:
5184                         if(dst == GL_SRC_COLOR)
5185                                 return false;
5186                         return true;
5187                 case GL_ONE:
5188                 case GL_SRC_COLOR:
5189                 case GL_ONE_MINUS_DST_COLOR:
5190                 case GL_DST_ALPHA:
5191                 case GL_ONE_MINUS_DST_ALPHA:
5192                         return true;
5193                 case GL_DST_COLOR:
5194                         if(dst == GL_ONE)
5195                                 return true;
5196                         return false;
5197                 default:
5198                         return false;
5199         }
5200 }
5201 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)
5202 {
5203         // select a permutation of the lighting shader appropriate to this
5204         // combination of texture, entity, light source, and fogging, only use the
5205         // minimum features necessary to avoid wasting rendering time in the
5206         // fragment shader on features that are not being used
5207         unsigned int permutation = 0;
5208         unsigned int mode = 0;
5209         qboolean allow_colormod;
5210         static float dummy_colormod[3] = {1, 1, 1};
5211         float *colormod = rsurface.colormod;
5212         float m16f[16];
5213         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5214         if (rsurfacepass == RSURFPASS_BACKGROUND)
5215         {
5216                 // distorted background
5217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5218                 {
5219                         mode = SHADERMODE_WATER;
5220                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5221                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5222                 }
5223                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5224                 {
5225                         mode = SHADERMODE_REFRACTION;
5226                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5227                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5228                 }
5229                 else
5230                 {
5231                         mode = SHADERMODE_GENERIC;
5232                         permutation |= SHADERPERMUTATION_DIFFUSE;
5233                         GL_BlendFunc(GL_ONE, GL_ZERO);
5234                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5235                 }
5236                 GL_AlphaTest(false);
5237         }
5238         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5239         {
5240                 if (r_glsl_offsetmapping.integer)
5241                 {
5242                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5243                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5244                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5245                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5246                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5247                         {
5248                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5249                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5250                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5251                         }
5252                 }
5253                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5254                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5255                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5256                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5257                 // normalmap (deferred prepass), may use alpha test on diffuse
5258                 mode = SHADERMODE_DEFERREDGEOMETRY;
5259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5261                 GL_AlphaTest(false);
5262                 GL_BlendFunc(GL_ONE, GL_ZERO);
5263                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5264         }
5265         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5266         {
5267                 if (r_glsl_offsetmapping.integer)
5268                 {
5269                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5270                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5271                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5272                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5273                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5274                         {
5275                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5276                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5277                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5278                         }
5279                 }
5280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5281                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5282                 // light source
5283                 mode = SHADERMODE_LIGHTSOURCE;
5284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5285                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5286                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5287                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5288                 if (diffusescale > 0)
5289                         permutation |= SHADERPERMUTATION_DIFFUSE;
5290                 if (specularscale > 0)
5291                 {
5292                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5293                         if (r_shadow_glossexact.integer)
5294                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5295                 }
5296                 if (r_refdef.fogenabled)
5297                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5298                 if (rsurface.texture->colormapping)
5299                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5300                 if (r_shadow_usingshadowmap2d)
5301                 {
5302                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5303                         if(r_shadow_shadowmapvsdct)
5304                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5305
5306                         if (r_shadow_shadowmapsampler)
5307                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5308                         if (r_shadow_shadowmappcf > 1)
5309                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5310                         else if (r_shadow_shadowmappcf)
5311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5312                 }
5313                 if (rsurface.texture->reflectmasktexture)
5314                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5315                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5316                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5317                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5318         }
5319         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5320         {
5321                 if (r_glsl_offsetmapping.integer)
5322                 {
5323                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5324                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5325                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5326                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5327                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5328                         {
5329                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5330                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5331                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5332                         }
5333                 }
5334                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5335                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5336                 // unshaded geometry (fullbright or ambient model lighting)
5337                 mode = SHADERMODE_FLATCOLOR;
5338                 ambientscale = diffusescale = specularscale = 0;
5339                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5340                         permutation |= SHADERPERMUTATION_GLOW;
5341                 if (r_refdef.fogenabled)
5342                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5343                 if (rsurface.texture->colormapping)
5344                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5345                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5346                 {
5347                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5348                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5349
5350                         if (r_shadow_shadowmapsampler)
5351                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5352                         if (r_shadow_shadowmappcf > 1)
5353                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5354                         else if (r_shadow_shadowmappcf)
5355                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5356                 }
5357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5358                         permutation |= SHADERPERMUTATION_REFLECTION;
5359                 if (rsurface.texture->reflectmasktexture)
5360                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5361                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5362                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5363                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5364         }
5365         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5366         {
5367                 if (r_glsl_offsetmapping.integer)
5368                 {
5369                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5370                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5371                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5372                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5373                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5374                         {
5375                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5376                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5377                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5378                         }
5379                 }
5380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5381                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5382                 // directional model lighting
5383                 mode = SHADERMODE_LIGHTDIRECTION;
5384                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5385                         permutation |= SHADERPERMUTATION_GLOW;
5386                 permutation |= SHADERPERMUTATION_DIFFUSE;
5387                 if (specularscale > 0)
5388                 {
5389                         permutation |= SHADERPERMUTATION_SPECULAR;
5390                         if (r_shadow_glossexact.integer)
5391                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5392                 }
5393                 if (r_refdef.fogenabled)
5394                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5395                 if (rsurface.texture->colormapping)
5396                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5397                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5398                 {
5399                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5400                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5401
5402                         if (r_shadow_shadowmapsampler)
5403                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5404                         if (r_shadow_shadowmappcf > 1)
5405                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5406                         else if (r_shadow_shadowmappcf)
5407                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5408                 }
5409                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5410                         permutation |= SHADERPERMUTATION_REFLECTION;
5411                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5412                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5413                 if (rsurface.texture->reflectmasktexture)
5414                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5415                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5416                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5417                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5418         }
5419         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5420         {
5421                 if (r_glsl_offsetmapping.integer)
5422                 {
5423                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5424                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5425                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5426                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5427                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5428                         {
5429                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5430                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5431                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5432                         }
5433                 }
5434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5435                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5436                 // ambient model lighting
5437                 mode = SHADERMODE_LIGHTDIRECTION;
5438                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5439                         permutation |= SHADERPERMUTATION_GLOW;
5440                 if (r_refdef.fogenabled)
5441                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5442                 if (rsurface.texture->colormapping)
5443                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5444                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5445                 {
5446                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5447                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5448
5449                         if (r_shadow_shadowmapsampler)
5450                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5451                         if (r_shadow_shadowmappcf > 1)
5452                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5453                         else if (r_shadow_shadowmappcf)
5454                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5455                 }
5456                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5457                         permutation |= SHADERPERMUTATION_REFLECTION;
5458                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5459                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5460                 if (rsurface.texture->reflectmasktexture)
5461                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5462                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5463                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5464                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5465         }
5466         else
5467         {
5468                 if (r_glsl_offsetmapping.integer)
5469                 {
5470                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5471                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5472                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5473                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5474                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5475                         {
5476                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5477                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5478                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5479                         }
5480                 }
5481                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5482                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5483                 // lightmapped wall
5484                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5485                         permutation |= SHADERPERMUTATION_GLOW;
5486                 if (r_refdef.fogenabled)
5487                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5488                 if (rsurface.texture->colormapping)
5489                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5490                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5491                 {
5492                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5493                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5494
5495                         if (r_shadow_shadowmapsampler)
5496                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5497                         if (r_shadow_shadowmappcf > 1)
5498                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5499                         else if (r_shadow_shadowmappcf)
5500                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5501                 }
5502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5503                         permutation |= SHADERPERMUTATION_REFLECTION;
5504                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5505                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5506                 if (rsurface.texture->reflectmasktexture)
5507                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5508                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5509                 {
5510                         // deluxemapping (light direction texture)
5511                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5512                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5513                         else
5514                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5515                         permutation |= SHADERPERMUTATION_DIFFUSE;
5516                         if (specularscale > 0)
5517                         {
5518                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5519                                 if (r_shadow_glossexact.integer)
5520                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5521                         }
5522                 }
5523                 else if (r_glsl_deluxemapping.integer >= 2)
5524                 {
5525                         // fake deluxemapping (uniform light direction in tangentspace)
5526                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5527                         permutation |= SHADERPERMUTATION_DIFFUSE;
5528                         if (specularscale > 0)
5529                         {
5530                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5531                                 if (r_shadow_glossexact.integer)
5532                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5533                         }
5534                 }
5535                 else if (rsurface.uselightmaptexture)
5536                 {
5537                         // ordinary lightmapping (q1bsp, q3bsp)
5538                         mode = SHADERMODE_LIGHTMAP;
5539                 }
5540                 else
5541                 {
5542                         // ordinary vertex coloring (q3bsp)
5543                         mode = SHADERMODE_VERTEXCOLOR;
5544                 }
5545                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5546                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5547                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5548         }
5549         if(!allow_colormod)
5550                 colormod = dummy_colormod;
5551         switch(vid.renderpath)
5552         {
5553         case RENDERPATH_D3D9:
5554 #ifdef SUPPORTD3D
5555                 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);
5556                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5557                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5558                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5559                 if (mode == SHADERMODE_LIGHTSOURCE)
5560                 {
5561                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5562                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5563                 }
5564                 else
5565                 {
5566                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5567                         {
5568                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5569                         }
5570                 }
5571                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5572                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5573                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5574                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5575                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5576
5577                 if (mode == SHADERMODE_LIGHTSOURCE)
5578                 {
5579                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5580                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5581                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5582                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5583                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5584
5585                         // additive passes are only darkened by fog, not tinted
5586                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5588                 }
5589                 else
5590                 {
5591                         if (mode == SHADERMODE_FLATCOLOR)
5592                         {
5593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5594                         }
5595                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5596                         {
5597                                 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]);
5598                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5599                                 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);
5600                                 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);
5601                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5602                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5603                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5604                         }
5605                         else
5606                         {
5607                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5608                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5609                                 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);
5610                                 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);
5611                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5612                         }
5613                         // additive passes are only darkened by fog, not tinted
5614                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5615                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5616                         else
5617                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5618                         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);
5619                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5620                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5621                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5622                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5623                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5624                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5625                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5626                 }
5627                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5628                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5629                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5630                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5631                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5632                 if (rsurface.texture->pantstexture)
5633                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5634                 else
5635                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5636                 if (rsurface.texture->shirttexture)
5637                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5638                 else
5639                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5640                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5641                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5642                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5643                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5644                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5645                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5646                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5647
5648                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5649                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5650                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5651                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5652                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5653                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5654                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5655                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5656                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5657                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5658                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5659                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5660                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5661                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5662                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5663                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5664                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5665                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5666                 {
5667                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5668                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5669                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5670                 }
5671                 else
5672                 {
5673                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5674                 }
5675 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5676 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5677                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5678                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5679                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5680                 {
5681                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5682                         if (rsurface.rtlight)
5683                         {
5684                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5685                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5686                         }
5687                 }
5688 #endif
5689                 break;
5690         case RENDERPATH_D3D10:
5691                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5692                 break;
5693         case RENDERPATH_D3D11:
5694                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5695                 break;
5696         case RENDERPATH_GL20:
5697                 if (gl_mesh_separatearrays.integer)
5698                 {
5699                         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);
5700                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5701                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5702                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5703                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5704                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5705                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5706                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5707                 }
5708                 else
5709                 {
5710                         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);
5711                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5712                 }
5713                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5714                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5715                 if (mode == SHADERMODE_LIGHTSOURCE)
5716                 {
5717                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5718                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5719                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5720                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5721                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5722                         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);
5723         
5724                         // additive passes are only darkened by fog, not tinted
5725                         if (r_glsl_permutation->loc_FogColor >= 0)
5726                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5727                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5728                 }
5729                 else
5730                 {
5731                         if (mode == SHADERMODE_FLATCOLOR)
5732                         {
5733                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5734                         }
5735                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5736                         {
5737                                 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]);
5738                                 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]);
5739                                 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);
5740                                 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);
5741                                 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);
5742                                 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]);
5743                                 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]);
5744                         }
5745                         else
5746                         {
5747                                 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]);
5748                                 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]);
5749                                 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);
5750                                 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);
5751                                 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);
5752                         }
5753                         // additive passes are only darkened by fog, not tinted
5754                         if (r_glsl_permutation->loc_FogColor >= 0)
5755                         {
5756                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5757                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5758                                 else
5759                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5760                         }
5761                         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);
5762                         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]);
5763                         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]);
5764                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5765                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5766                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5767                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5768                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5769                 }
5770                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5771                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5772                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5773                 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]);
5774                 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]);
5775
5776                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5777                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5778                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5779                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5780                 {
5781                         if (rsurface.texture->pantstexture)
5782                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5783                         else
5784                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5785                 }
5786                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5787                 {
5788                         if (rsurface.texture->shirttexture)
5789                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5790                         else
5791                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5792                 }
5793                 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]);
5794                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5795                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5796                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5797                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5798                 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]);
5799                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5800
5801         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5802         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5803         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5804                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5805                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5806                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5807                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5808                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5809                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5810                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5811                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5812                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5813                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5814                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5815                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5816                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5817                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5818                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5819                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5820                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5821                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5822                 {
5823                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5824                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5825                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5826                 }
5827                 else
5828                 {
5829                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5830                 }
5831 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5832 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5833                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5834                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5835                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5836                 {
5837                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5838                         if (rsurface.rtlight)
5839                         {
5840                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5841                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5842                         }
5843                 }
5844                 CHECKGLERROR
5845                 break;
5846         case RENDERPATH_CGGL:
5847 #ifdef SUPPORTCG
5848                 if (gl_mesh_separatearrays.integer)
5849                 {
5850                         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);
5851                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5852                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5853                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5854                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5855                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5856                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5857                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5858                 }
5859                 else
5860                 {
5861                         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);
5862                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5863                 }
5864                 R_SetupShader_SetPermutationCG(mode, permutation);
5865                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5866                 if (mode == SHADERMODE_LIGHTSOURCE)
5867                 {
5868                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5869                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5870                 }
5871                 else
5872                 {
5873                         if (mode == SHADERMODE_LIGHTDIRECTION)
5874                         {
5875                                 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
5876                         }
5877                 }
5878                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5879                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5880                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5881                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5882                 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
5883                 CHECKGLERROR
5884
5885                 if (mode == SHADERMODE_LIGHTSOURCE)
5886                 {
5887                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5888                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5889                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5890                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5891                         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
5892
5893                         // additive passes are only darkened by fog, not tinted
5894                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5895                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5896                 }
5897                 else
5898                 {
5899                         if (mode == SHADERMODE_FLATCOLOR)
5900                         {
5901                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5902                         }
5903                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5904                         {
5905                                 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
5906                                 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
5907                                 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
5908                                 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
5909                                 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
5910                                 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
5911                                 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
5912                         }
5913                         else
5914                         {
5915                                 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
5916                                 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
5917                                 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
5918                                 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
5919                                 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
5920                         }
5921                         // additive passes are only darkened by fog, not tinted
5922                         if (r_cg_permutation->fp_FogColor)
5923                         {
5924                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5925                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5926                                 else
5927                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5928                                 CHECKCGERROR
5929                         }
5930                         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
5931                         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
5932                         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
5933                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5934                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5935                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5936                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5937                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5938                 }
5939                 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
5940                 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
5941                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5942                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5943                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5944                 if (r_cg_permutation->fp_Color_Pants)
5945                 {
5946                         if (rsurface.texture->pantstexture)
5947                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5948                         else
5949                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5950                         CHECKCGERROR
5951                 }
5952                 if (r_cg_permutation->fp_Color_Shirt)
5953                 {
5954                         if (rsurface.texture->shirttexture)
5955                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5956                         else
5957                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5958                         CHECKCGERROR
5959                 }
5960                 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
5961                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5962                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5963                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5964                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5965                 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
5966                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5967
5968         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5969         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5970         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5971                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5972                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5973                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5974                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5975                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5976                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5977                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5978                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5979                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5980                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5981                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5982                 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
5983                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5984                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5985                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5986                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5987                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5988                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5989                 {
5990                         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
5991                         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
5992                         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
5993                 }
5994                 else
5995                 {
5996                         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
5997                 }
5998                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5999                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6000                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6001                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6002                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6003                 {
6004                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6005                         if (rsurface.rtlight)
6006                         {
6007                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6008                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6009                         }
6010                 }
6011
6012                 CHECKGLERROR
6013 #endif
6014                 break;
6015         case RENDERPATH_GL13:
6016         case RENDERPATH_GL11:
6017                 break;
6018         }
6019 }
6020
6021 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6022 {
6023         // select a permutation of the lighting shader appropriate to this
6024         // combination of texture, entity, light source, and fogging, only use the
6025         // minimum features necessary to avoid wasting rendering time in the
6026         // fragment shader on features that are not being used
6027         unsigned int permutation = 0;
6028         unsigned int mode = 0;
6029         const float *lightcolorbase = rtlight->currentcolor;
6030         float ambientscale = rtlight->ambientscale;
6031         float diffusescale = rtlight->diffusescale;
6032         float specularscale = rtlight->specularscale;
6033         // this is the location of the light in view space
6034         vec3_t viewlightorigin;
6035         // this transforms from view space (camera) to light space (cubemap)
6036         matrix4x4_t viewtolight;
6037         matrix4x4_t lighttoview;
6038         float viewtolight16f[16];
6039         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6040         // light source
6041         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6042         if (rtlight->currentcubemap != r_texture_whitecube)
6043                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6044         if (diffusescale > 0)
6045                 permutation |= SHADERPERMUTATION_DIFFUSE;
6046         if (specularscale > 0)
6047         {
6048                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6049                 if (r_shadow_glossexact.integer)
6050                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6051         }
6052         if (r_shadow_usingshadowmap2d)
6053         {
6054                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6055                 if (r_shadow_shadowmapvsdct)
6056                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6057
6058                 if (r_shadow_shadowmapsampler)
6059                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6060                 if (r_shadow_shadowmappcf > 1)
6061                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6062                 else if (r_shadow_shadowmappcf)
6063                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6064         }
6065         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6066         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6067         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6068         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6069         switch(vid.renderpath)
6070         {
6071         case RENDERPATH_D3D9:
6072 #ifdef SUPPORTD3D
6073                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6074                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6075                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6076                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6077                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6078                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6079                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6080                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6081                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6082                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6083                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6084
6085                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6086                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6087                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6088                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6089                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6090                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6091 #endif
6092                 break;
6093         case RENDERPATH_D3D10:
6094                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6095                 break;
6096         case RENDERPATH_D3D11:
6097                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6098                 break;
6099         case RENDERPATH_GL20:
6100                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6101                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6102                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6103                 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);
6104                 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);
6105                 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);
6106                 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]);
6107                 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]);
6108                 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));
6109                 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]);
6110                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6111
6112                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6113                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6114                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6115                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6116                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6117                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6118                 break;
6119         case RENDERPATH_CGGL:
6120 #ifdef SUPPORTCG
6121                 R_SetupShader_SetPermutationCG(mode, permutation);
6122                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6123                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6124                 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
6125                 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
6126                 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
6127                 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
6128                 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
6129                 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
6130                 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
6131                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6132
6133                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6134                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6135                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6136                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6137                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6139 #endif
6140                 break;
6141         case RENDERPATH_GL13:
6142         case RENDERPATH_GL11:
6143                 break;
6144         }
6145 }
6146
6147 #define SKINFRAME_HASH 1024
6148
6149 typedef struct
6150 {
6151         int loadsequence; // incremented each level change
6152         memexpandablearray_t array;
6153         skinframe_t *hash[SKINFRAME_HASH];
6154 }
6155 r_skinframe_t;
6156 r_skinframe_t r_skinframe;
6157
6158 void R_SkinFrame_PrepareForPurge(void)
6159 {
6160         r_skinframe.loadsequence++;
6161         // wrap it without hitting zero
6162         if (r_skinframe.loadsequence >= 200)
6163                 r_skinframe.loadsequence = 1;
6164 }
6165
6166 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6167 {
6168         if (!skinframe)
6169                 return;
6170         // mark the skinframe as used for the purging code
6171         skinframe->loadsequence = r_skinframe.loadsequence;
6172 }
6173
6174 void R_SkinFrame_Purge(void)
6175 {
6176         int i;
6177         skinframe_t *s;
6178         for (i = 0;i < SKINFRAME_HASH;i++)
6179         {
6180                 for (s = r_skinframe.hash[i];s;s = s->next)
6181                 {
6182                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6183                         {
6184                                 if (s->merged == s->base)
6185                                         s->merged = NULL;
6186                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6187                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6188                                 R_PurgeTexture(s->merged);s->merged = NULL;
6189                                 R_PurgeTexture(s->base  );s->base   = NULL;
6190                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6191                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6192                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6193                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6194                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6195                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6196                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6197                                 s->loadsequence = 0;
6198                         }
6199                 }
6200         }
6201 }
6202
6203 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6204         skinframe_t *item;
6205         char basename[MAX_QPATH];
6206
6207         Image_StripImageExtension(name, basename, sizeof(basename));
6208
6209         if( last == NULL ) {
6210                 int hashindex;
6211                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6212                 item = r_skinframe.hash[hashindex];
6213         } else {
6214                 item = last->next;
6215         }
6216
6217         // linearly search through the hash bucket
6218         for( ; item ; item = item->next ) {
6219                 if( !strcmp( item->basename, basename ) ) {
6220                         return item;
6221                 }
6222         }
6223         return NULL;
6224 }
6225
6226 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6227 {
6228         skinframe_t *item;
6229         int hashindex;
6230         char basename[MAX_QPATH];
6231
6232         Image_StripImageExtension(name, basename, sizeof(basename));
6233
6234         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6235         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6236                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6237                         break;
6238
6239         if (!item) {
6240                 rtexture_t *dyntexture;
6241                 // check whether its a dynamic texture
6242                 dyntexture = CL_GetDynTexture( basename );
6243                 if (!add && !dyntexture)
6244                         return NULL;
6245                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6246                 memset(item, 0, sizeof(*item));
6247                 strlcpy(item->basename, basename, sizeof(item->basename));
6248                 item->base = dyntexture; // either NULL or dyntexture handle
6249                 item->textureflags = textureflags;
6250                 item->comparewidth = comparewidth;
6251                 item->compareheight = compareheight;
6252                 item->comparecrc = comparecrc;
6253                 item->next = r_skinframe.hash[hashindex];
6254                 r_skinframe.hash[hashindex] = item;
6255         }
6256         else if( item->base == NULL )
6257         {
6258                 rtexture_t *dyntexture;
6259                 // check whether its a dynamic texture
6260                 // 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]
6261                 dyntexture = CL_GetDynTexture( basename );
6262                 item->base = dyntexture; // either NULL or dyntexture handle
6263         }
6264
6265         R_SkinFrame_MarkUsed(item);
6266         return item;
6267 }
6268
6269 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6270         { \
6271                 unsigned long long avgcolor[5], wsum; \
6272                 int pix, comp, w; \
6273                 avgcolor[0] = 0; \
6274                 avgcolor[1] = 0; \
6275                 avgcolor[2] = 0; \
6276                 avgcolor[3] = 0; \
6277                 avgcolor[4] = 0; \
6278                 wsum = 0; \
6279                 for(pix = 0; pix < cnt; ++pix) \
6280                 { \
6281                         w = 0; \
6282                         for(comp = 0; comp < 3; ++comp) \
6283                                 w += getpixel; \
6284                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6285                         { \
6286                                 ++wsum; \
6287                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6288                                 w = getpixel; \
6289                                 for(comp = 0; comp < 3; ++comp) \
6290                                         avgcolor[comp] += getpixel * w; \
6291                                 avgcolor[3] += w; \
6292                         } \
6293                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6294                         avgcolor[4] += getpixel; \
6295                 } \
6296                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6297                         avgcolor[3] = 1; \
6298                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6299                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6300                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6301                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6302         }
6303
6304 extern cvar_t gl_picmip;
6305 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6306 {
6307         int j;
6308         unsigned char *pixels;
6309         unsigned char *bumppixels;
6310         unsigned char *basepixels = NULL;
6311         int basepixels_width = 0;
6312         int basepixels_height = 0;
6313         skinframe_t *skinframe;
6314         rtexture_t *ddsbase = NULL;
6315         qboolean ddshasalpha = false;
6316         float ddsavgcolor[4];
6317         char basename[MAX_QPATH];
6318         int miplevel = R_PicmipForFlags(textureflags);
6319         int savemiplevel = miplevel;
6320         int mymiplevel;
6321
6322         if (cls.state == ca_dedicated)
6323                 return NULL;
6324
6325         // return an existing skinframe if already loaded
6326         // if loading of the first image fails, don't make a new skinframe as it
6327         // would cause all future lookups of this to be missing
6328         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6329         if (skinframe && skinframe->base)
6330                 return skinframe;
6331
6332         Image_StripImageExtension(name, basename, sizeof(basename));
6333
6334         // check for DDS texture file first
6335         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6336         {
6337                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6338                 if (basepixels == NULL)
6339                         return NULL;
6340         }
6341
6342         // FIXME handle miplevel
6343
6344         if (developer_loading.integer)
6345                 Con_Printf("loading skin \"%s\"\n", name);
6346
6347         // we've got some pixels to store, so really allocate this new texture now
6348         if (!skinframe)
6349                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6350         skinframe->stain = NULL;
6351         skinframe->merged = NULL;
6352         skinframe->base = NULL;
6353         skinframe->pants = NULL;
6354         skinframe->shirt = NULL;
6355         skinframe->nmap = NULL;
6356         skinframe->gloss = NULL;
6357         skinframe->glow = NULL;
6358         skinframe->fog = NULL;
6359         skinframe->reflect = NULL;
6360         skinframe->hasalpha = false;
6361
6362         if (ddsbase)
6363         {
6364                 skinframe->base = ddsbase;
6365                 skinframe->hasalpha = ddshasalpha;
6366                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6367                 if (r_loadfog && skinframe->hasalpha)
6368                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6369                 //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]);
6370         }
6371         else
6372         {
6373                 basepixels_width = image_width;
6374                 basepixels_height = image_height;
6375                 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);
6376                 if (textureflags & TEXF_ALPHA)
6377                 {
6378                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6379                         {
6380                                 if (basepixels[j] < 255)
6381                                 {
6382                                         skinframe->hasalpha = true;
6383                                         break;
6384                                 }
6385                         }
6386                         if (r_loadfog && skinframe->hasalpha)
6387                         {
6388                                 // has transparent pixels
6389                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6390                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6391                                 {
6392                                         pixels[j+0] = 255;
6393                                         pixels[j+1] = 255;
6394                                         pixels[j+2] = 255;
6395                                         pixels[j+3] = basepixels[j+3];
6396                                 }
6397                                 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);
6398                                 Mem_Free(pixels);
6399                         }
6400                 }
6401                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6402                 //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]);
6403                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6404                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6405                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6406                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6407         }
6408
6409         if (r_loaddds)
6410         {
6411                 mymiplevel = savemiplevel;
6412                 if (r_loadnormalmap)
6413                         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);
6414                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6415                 if (r_loadgloss)
6416                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6417                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6418                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6419                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6420         }
6421
6422         // _norm is the name used by tenebrae and has been adopted as standard
6423         if (r_loadnormalmap && skinframe->nmap == NULL)
6424         {
6425                 mymiplevel = savemiplevel;
6426                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6427                 {
6428                         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);
6429                         Mem_Free(pixels);
6430                         pixels = NULL;
6431                 }
6432                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6433                 {
6434                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6435                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6436                         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);
6437                         Mem_Free(pixels);
6438                         Mem_Free(bumppixels);
6439                 }
6440                 else if (r_shadow_bumpscale_basetexture.value > 0)
6441                 {
6442                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6443                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6444                         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);
6445                         Mem_Free(pixels);
6446                 }
6447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6448                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6449         }
6450
6451         // _luma is supported only for tenebrae compatibility
6452         // _glow is the preferred name
6453         mymiplevel = savemiplevel;
6454         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))))
6455         {
6456                 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);
6457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6458                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6459                 Mem_Free(pixels);pixels = NULL;
6460         }
6461
6462         mymiplevel = savemiplevel;
6463         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6464         {
6465                 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);
6466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6467                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6468                 Mem_Free(pixels);
6469                 pixels = NULL;
6470         }
6471
6472         mymiplevel = savemiplevel;
6473         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6474         {
6475                 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);
6476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6477                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6478                 Mem_Free(pixels);
6479                 pixels = NULL;
6480         }
6481
6482         mymiplevel = savemiplevel;
6483         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6484         {
6485                 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);
6486                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6487                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6488                 Mem_Free(pixels);
6489                 pixels = NULL;
6490         }
6491
6492         mymiplevel = savemiplevel;
6493         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6494         {
6495                 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);
6496                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6497                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6498                 Mem_Free(pixels);
6499                 pixels = NULL;
6500         }
6501
6502         if (basepixels)
6503                 Mem_Free(basepixels);
6504
6505         return skinframe;
6506 }
6507
6508 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6509 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6510 {
6511         int i;
6512         unsigned char *temp1, *temp2;
6513         skinframe_t *skinframe;
6514
6515         if (cls.state == ca_dedicated)
6516                 return NULL;
6517
6518         // if already loaded just return it, otherwise make a new skinframe
6519         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6520         if (skinframe && skinframe->base)
6521                 return skinframe;
6522
6523         skinframe->stain = NULL;
6524         skinframe->merged = NULL;
6525         skinframe->base = NULL;
6526         skinframe->pants = NULL;
6527         skinframe->shirt = NULL;
6528         skinframe->nmap = NULL;
6529         skinframe->gloss = NULL;
6530         skinframe->glow = NULL;
6531         skinframe->fog = NULL;
6532         skinframe->reflect = NULL;
6533         skinframe->hasalpha = false;
6534
6535         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6536         if (!skindata)
6537                 return NULL;
6538
6539         if (developer_loading.integer)
6540                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6541
6542         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6543         {
6544                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6545                 temp2 = temp1 + width * height * 4;
6546                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6547                 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);
6548                 Mem_Free(temp1);
6549         }
6550         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6551         if (textureflags & TEXF_ALPHA)
6552         {
6553                 for (i = 3;i < width * height * 4;i += 4)
6554                 {
6555                         if (skindata[i] < 255)
6556                         {
6557                                 skinframe->hasalpha = true;
6558                                 break;
6559                         }
6560                 }
6561                 if (r_loadfog && skinframe->hasalpha)
6562                 {
6563                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6564                         memcpy(fogpixels, skindata, width * height * 4);
6565                         for (i = 0;i < width * height * 4;i += 4)
6566                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6567                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6568                         Mem_Free(fogpixels);
6569                 }
6570         }
6571
6572         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6573         //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]);
6574
6575         return skinframe;
6576 }
6577
6578 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6579 {
6580         int i;
6581         int featuresmask;
6582         skinframe_t *skinframe;
6583
6584         if (cls.state == ca_dedicated)
6585                 return NULL;
6586
6587         // if already loaded just return it, otherwise make a new skinframe
6588         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6589         if (skinframe && skinframe->base)
6590                 return skinframe;
6591
6592         skinframe->stain = NULL;
6593         skinframe->merged = NULL;
6594         skinframe->base = NULL;
6595         skinframe->pants = NULL;
6596         skinframe->shirt = NULL;
6597         skinframe->nmap = NULL;
6598         skinframe->gloss = NULL;
6599         skinframe->glow = NULL;
6600         skinframe->fog = NULL;
6601         skinframe->reflect = NULL;
6602         skinframe->hasalpha = false;
6603
6604         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6605         if (!skindata)
6606                 return NULL;
6607
6608         if (developer_loading.integer)
6609                 Con_Printf("loading quake skin \"%s\"\n", name);
6610
6611         // 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)
6612         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6613         memcpy(skinframe->qpixels, skindata, width*height);
6614         skinframe->qwidth = width;
6615         skinframe->qheight = height;
6616
6617         featuresmask = 0;
6618         for (i = 0;i < width * height;i++)
6619                 featuresmask |= palette_featureflags[skindata[i]];
6620
6621         skinframe->hasalpha = false;
6622         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6623         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6624         skinframe->qgeneratemerged = true;
6625         skinframe->qgeneratebase = skinframe->qhascolormapping;
6626         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6627
6628         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6629         //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]);
6630
6631         return skinframe;
6632 }
6633
6634 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6635 {
6636         int width;
6637         int height;
6638         unsigned char *skindata;
6639
6640         if (!skinframe->qpixels)
6641                 return;
6642
6643         if (!skinframe->qhascolormapping)
6644                 colormapped = false;
6645
6646         if (colormapped)
6647         {
6648                 if (!skinframe->qgeneratebase)
6649                         return;
6650         }
6651         else
6652         {
6653                 if (!skinframe->qgeneratemerged)
6654                         return;
6655         }
6656
6657         width = skinframe->qwidth;
6658         height = skinframe->qheight;
6659         skindata = skinframe->qpixels;
6660
6661         if (skinframe->qgeneratenmap)
6662         {
6663                 unsigned char *temp1, *temp2;
6664                 skinframe->qgeneratenmap = false;
6665                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6666                 temp2 = temp1 + width * height * 4;
6667                 // use either a custom palette or the quake palette
6668                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6669                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6670                 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);
6671                 Mem_Free(temp1);
6672         }
6673
6674         if (skinframe->qgenerateglow)
6675         {
6676                 skinframe->qgenerateglow = false;
6677                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6678         }
6679
6680         if (colormapped)
6681         {
6682                 skinframe->qgeneratebase = false;
6683                 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);
6684                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6685                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6686         }
6687         else
6688         {
6689                 skinframe->qgeneratemerged = false;
6690                 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);
6691         }
6692
6693         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6694         {
6695                 Mem_Free(skinframe->qpixels);
6696                 skinframe->qpixels = NULL;
6697         }
6698 }
6699
6700 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)
6701 {
6702         int i;
6703         skinframe_t *skinframe;
6704
6705         if (cls.state == ca_dedicated)
6706                 return NULL;
6707
6708         // if already loaded just return it, otherwise make a new skinframe
6709         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6710         if (skinframe && skinframe->base)
6711                 return skinframe;
6712
6713         skinframe->stain = NULL;
6714         skinframe->merged = NULL;
6715         skinframe->base = NULL;
6716         skinframe->pants = NULL;
6717         skinframe->shirt = NULL;
6718         skinframe->nmap = NULL;
6719         skinframe->gloss = NULL;
6720         skinframe->glow = NULL;
6721         skinframe->fog = NULL;
6722         skinframe->reflect = NULL;
6723         skinframe->hasalpha = false;
6724
6725         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6726         if (!skindata)
6727                 return NULL;
6728
6729         if (developer_loading.integer)
6730                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6731
6732         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6733         if (textureflags & TEXF_ALPHA)
6734         {
6735                 for (i = 0;i < width * height;i++)
6736                 {
6737                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6738                         {
6739                                 skinframe->hasalpha = true;
6740                                 break;
6741                         }
6742                 }
6743                 if (r_loadfog && skinframe->hasalpha)
6744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6745         }
6746
6747         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6748         //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]);
6749
6750         return skinframe;
6751 }
6752
6753 skinframe_t *R_SkinFrame_LoadMissing(void)
6754 {
6755         skinframe_t *skinframe;
6756
6757         if (cls.state == ca_dedicated)
6758                 return NULL;
6759
6760         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6761         skinframe->stain = NULL;
6762         skinframe->merged = NULL;
6763         skinframe->base = NULL;
6764         skinframe->pants = NULL;
6765         skinframe->shirt = NULL;
6766         skinframe->nmap = NULL;
6767         skinframe->gloss = NULL;
6768         skinframe->glow = NULL;
6769         skinframe->fog = NULL;
6770         skinframe->reflect = NULL;
6771         skinframe->hasalpha = false;
6772
6773         skinframe->avgcolor[0] = rand() / RAND_MAX;
6774         skinframe->avgcolor[1] = rand() / RAND_MAX;
6775         skinframe->avgcolor[2] = rand() / RAND_MAX;
6776         skinframe->avgcolor[3] = 1;
6777
6778         return skinframe;
6779 }
6780
6781 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6782 typedef struct suffixinfo_s
6783 {
6784         const char *suffix;
6785         qboolean flipx, flipy, flipdiagonal;
6786 }
6787 suffixinfo_t;
6788 static suffixinfo_t suffix[3][6] =
6789 {
6790         {
6791                 {"px",   false, false, false},
6792                 {"nx",   false, false, false},
6793                 {"py",   false, false, false},
6794                 {"ny",   false, false, false},
6795                 {"pz",   false, false, false},
6796                 {"nz",   false, false, false}
6797         },
6798         {
6799                 {"posx", false, false, false},
6800                 {"negx", false, false, false},
6801                 {"posy", false, false, false},
6802                 {"negy", false, false, false},
6803                 {"posz", false, false, false},
6804                 {"negz", false, false, false}
6805         },
6806         {
6807                 {"rt",    true, false,  true},
6808                 {"lf",   false,  true,  true},
6809                 {"ft",    true,  true, false},
6810                 {"bk",   false, false, false},
6811                 {"up",    true, false,  true},
6812                 {"dn",    true, false,  true}
6813         }
6814 };
6815
6816 static int componentorder[4] = {0, 1, 2, 3};
6817
6818 rtexture_t *R_LoadCubemap(const char *basename)
6819 {
6820         int i, j, cubemapsize;
6821         unsigned char *cubemappixels, *image_buffer;
6822         rtexture_t *cubemaptexture;
6823         char name[256];
6824         // must start 0 so the first loadimagepixels has no requested width/height
6825         cubemapsize = 0;
6826         cubemappixels = NULL;
6827         cubemaptexture = NULL;
6828         // keep trying different suffix groups (posx, px, rt) until one loads
6829         for (j = 0;j < 3 && !cubemappixels;j++)
6830         {
6831                 // load the 6 images in the suffix group
6832                 for (i = 0;i < 6;i++)
6833                 {
6834                         // generate an image name based on the base and and suffix
6835                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6836                         // load it
6837                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6838                         {
6839                                 // an image loaded, make sure width and height are equal
6840                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6841                                 {
6842                                         // if this is the first image to load successfully, allocate the cubemap memory
6843                                         if (!cubemappixels && image_width >= 1)
6844                                         {
6845                                                 cubemapsize = image_width;
6846                                                 // note this clears to black, so unavailable sides are black
6847                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6848                                         }
6849                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6850                                         if (cubemappixels)
6851                                                 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);
6852                                 }
6853                                 else
6854                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6855                                 // free the image
6856                                 Mem_Free(image_buffer);
6857                         }
6858                 }
6859         }
6860         // if a cubemap loaded, upload it
6861         if (cubemappixels)
6862         {
6863                 if (developer_loading.integer)
6864                         Con_Printf("loading cubemap \"%s\"\n", basename);
6865
6866                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6867                 Mem_Free(cubemappixels);
6868         }
6869         else
6870         {
6871                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6872                 if (developer_loading.integer)
6873                 {
6874                         Con_Printf("(tried tried images ");
6875                         for (j = 0;j < 3;j++)
6876                                 for (i = 0;i < 6;i++)
6877                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6878                         Con_Print(" and was unable to find any of them).\n");
6879                 }
6880         }
6881         return cubemaptexture;
6882 }
6883
6884 rtexture_t *R_GetCubemap(const char *basename)
6885 {
6886         int i;
6887         for (i = 0;i < r_texture_numcubemaps;i++)
6888                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6889                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6890         if (i >= MAX_CUBEMAPS)
6891                 return r_texture_whitecube;
6892         r_texture_numcubemaps++;
6893         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6894         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6895         return r_texture_cubemaps[i].texture;
6896 }
6897
6898 void R_FreeCubemaps(void)
6899 {
6900         int i;
6901         for (i = 0;i < r_texture_numcubemaps;i++)
6902         {
6903                 if (developer_loading.integer)
6904                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6905                 if (r_texture_cubemaps[i].texture)
6906                         R_FreeTexture(r_texture_cubemaps[i].texture);
6907         }
6908         r_texture_numcubemaps = 0;
6909 }
6910
6911 void R_Main_FreeViewCache(void)
6912 {
6913         if (r_refdef.viewcache.entityvisible)
6914                 Mem_Free(r_refdef.viewcache.entityvisible);
6915         if (r_refdef.viewcache.world_pvsbits)
6916                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6917         if (r_refdef.viewcache.world_leafvisible)
6918                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6919         if (r_refdef.viewcache.world_surfacevisible)
6920                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6921         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6922 }
6923
6924 void R_Main_ResizeViewCache(void)
6925 {
6926         int numentities = r_refdef.scene.numentities;
6927         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6928         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6929         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6930         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6931         if (r_refdef.viewcache.maxentities < numentities)
6932         {
6933                 r_refdef.viewcache.maxentities = numentities;
6934                 if (r_refdef.viewcache.entityvisible)
6935                         Mem_Free(r_refdef.viewcache.entityvisible);
6936                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6937         }
6938         if (r_refdef.viewcache.world_numclusters != numclusters)
6939         {
6940                 r_refdef.viewcache.world_numclusters = numclusters;
6941                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6942                 if (r_refdef.viewcache.world_pvsbits)
6943                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6944                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6945         }
6946         if (r_refdef.viewcache.world_numleafs != numleafs)
6947         {
6948                 r_refdef.viewcache.world_numleafs = numleafs;
6949                 if (r_refdef.viewcache.world_leafvisible)
6950                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6951                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6952         }
6953         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6954         {
6955                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6956                 if (r_refdef.viewcache.world_surfacevisible)
6957                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6958                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6959         }
6960 }
6961
6962 extern rtexture_t *loadingscreentexture;
6963 void gl_main_start(void)
6964 {
6965         loadingscreentexture = NULL;
6966         r_texture_blanknormalmap = NULL;
6967         r_texture_white = NULL;
6968         r_texture_grey128 = NULL;
6969         r_texture_black = NULL;
6970         r_texture_whitecube = NULL;
6971         r_texture_normalizationcube = NULL;
6972         r_texture_fogattenuation = NULL;
6973         r_texture_fogheighttexture = NULL;
6974         r_texture_gammaramps = NULL;
6975         r_texture_numcubemaps = 0;
6976
6977         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6978         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6979
6980         switch(vid.renderpath)
6981         {
6982         case RENDERPATH_GL20:
6983         case RENDERPATH_CGGL:
6984         case RENDERPATH_D3D9:
6985         case RENDERPATH_D3D10:
6986         case RENDERPATH_D3D11:
6987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6988                 Cvar_SetValueQuick(&gl_combine, 1);
6989                 Cvar_SetValueQuick(&r_glsl, 1);
6990                 r_loadnormalmap = true;
6991                 r_loadgloss = true;
6992                 r_loadfog = false;
6993                 break;
6994         case RENDERPATH_GL13:
6995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6996                 Cvar_SetValueQuick(&gl_combine, 1);
6997                 Cvar_SetValueQuick(&r_glsl, 0);
6998                 r_loadnormalmap = false;
6999                 r_loadgloss = false;
7000                 r_loadfog = true;
7001                 break;
7002         case RENDERPATH_GL11:
7003                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7004                 Cvar_SetValueQuick(&gl_combine, 0);
7005                 Cvar_SetValueQuick(&r_glsl, 0);
7006                 r_loadnormalmap = false;
7007                 r_loadgloss = false;
7008                 r_loadfog = true;
7009                 break;
7010         }
7011
7012         R_AnimCache_Free();
7013         R_FrameData_Reset();
7014
7015         r_numqueries = 0;
7016         r_maxqueries = 0;
7017         memset(r_queries, 0, sizeof(r_queries));
7018
7019         r_qwskincache = NULL;
7020         r_qwskincache_size = 0;
7021
7022         // set up r_skinframe loading system for textures
7023         memset(&r_skinframe, 0, sizeof(r_skinframe));
7024         r_skinframe.loadsequence = 1;
7025         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7026
7027         r_main_texturepool = R_AllocTexturePool();
7028         R_BuildBlankTextures();
7029         R_BuildNoTexture();
7030         if (vid.support.arb_texture_cube_map)
7031         {
7032                 R_BuildWhiteCube();
7033                 R_BuildNormalizationCube();
7034         }
7035         r_texture_fogattenuation = NULL;
7036         r_texture_fogheighttexture = NULL;
7037         r_texture_gammaramps = NULL;
7038         //r_texture_fogintensity = NULL;
7039         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7040         memset(&r_waterstate, 0, sizeof(r_waterstate));
7041         r_glsl_permutation = NULL;
7042         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7043         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7044         glslshaderstring = NULL;
7045 #ifdef SUPPORTCG
7046         r_cg_permutation = NULL;
7047         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7048         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7049         cgshaderstring = NULL;
7050 #endif
7051 #ifdef SUPPORTD3D
7052         r_hlsl_permutation = NULL;
7053         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7054         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7055         hlslshaderstring = NULL;
7056 #endif
7057         memset(&r_svbsp, 0, sizeof (r_svbsp));
7058
7059         r_refdef.fogmasktable_density = 0;
7060 }
7061
7062 void gl_main_shutdown(void)
7063 {
7064         R_AnimCache_Free();
7065         R_FrameData_Reset();
7066
7067         R_Main_FreeViewCache();
7068
7069         switch(vid.renderpath)
7070         {
7071         case RENDERPATH_GL11:
7072         case RENDERPATH_GL13:
7073         case RENDERPATH_GL20:
7074         case RENDERPATH_CGGL:
7075                 if (r_maxqueries)
7076                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7077                 break;
7078         case RENDERPATH_D3D9:
7079                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7080                 break;
7081         case RENDERPATH_D3D10:
7082                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7083                 break;
7084         case RENDERPATH_D3D11:
7085                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7086                 break;
7087         }
7088
7089         r_numqueries = 0;
7090         r_maxqueries = 0;
7091         memset(r_queries, 0, sizeof(r_queries));
7092
7093         r_qwskincache = NULL;
7094         r_qwskincache_size = 0;
7095
7096         // clear out the r_skinframe state
7097         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7098         memset(&r_skinframe, 0, sizeof(r_skinframe));
7099
7100         if (r_svbsp.nodes)
7101                 Mem_Free(r_svbsp.nodes);
7102         memset(&r_svbsp, 0, sizeof (r_svbsp));
7103         R_FreeTexturePool(&r_main_texturepool);
7104         loadingscreentexture = NULL;
7105         r_texture_blanknormalmap = NULL;
7106         r_texture_white = NULL;
7107         r_texture_grey128 = NULL;
7108         r_texture_black = NULL;
7109         r_texture_whitecube = NULL;
7110         r_texture_normalizationcube = NULL;
7111         r_texture_fogattenuation = NULL;
7112         r_texture_fogheighttexture = NULL;
7113         r_texture_gammaramps = NULL;
7114         r_texture_numcubemaps = 0;
7115         //r_texture_fogintensity = NULL;
7116         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7117         memset(&r_waterstate, 0, sizeof(r_waterstate));
7118         R_GLSL_Restart_f();
7119 }
7120
7121 extern void CL_ParseEntityLump(char *entitystring);
7122 void gl_main_newmap(void)
7123 {
7124         // FIXME: move this code to client
7125         char *entities, entname[MAX_QPATH];
7126         if (r_qwskincache)
7127                 Mem_Free(r_qwskincache);
7128         r_qwskincache = NULL;
7129         r_qwskincache_size = 0;
7130         if (cl.worldmodel)
7131         {
7132                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7133                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7134                 {
7135                         CL_ParseEntityLump(entities);
7136                         Mem_Free(entities);
7137                         return;
7138                 }
7139                 if (cl.worldmodel->brush.entities)
7140                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7141         }
7142         R_Main_FreeViewCache();
7143
7144         R_FrameData_Reset();
7145 }
7146
7147 void GL_Main_Init(void)
7148 {
7149         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7150
7151         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7152         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7153         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7154         if (gamemode == GAME_NEHAHRA)
7155         {
7156                 Cvar_RegisterVariable (&gl_fogenable);
7157                 Cvar_RegisterVariable (&gl_fogdensity);
7158                 Cvar_RegisterVariable (&gl_fogred);
7159                 Cvar_RegisterVariable (&gl_foggreen);
7160                 Cvar_RegisterVariable (&gl_fogblue);
7161                 Cvar_RegisterVariable (&gl_fogstart);
7162                 Cvar_RegisterVariable (&gl_fogend);
7163                 Cvar_RegisterVariable (&gl_skyclip);
7164         }
7165         Cvar_RegisterVariable(&r_motionblur);
7166         Cvar_RegisterVariable(&r_motionblur_maxblur);
7167         Cvar_RegisterVariable(&r_motionblur_bmin);
7168         Cvar_RegisterVariable(&r_motionblur_vmin);
7169         Cvar_RegisterVariable(&r_motionblur_vmax);
7170         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7171         Cvar_RegisterVariable(&r_motionblur_randomize);
7172         Cvar_RegisterVariable(&r_damageblur);
7173         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7174         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7175         Cvar_RegisterVariable(&r_equalize_entities_by);
7176         Cvar_RegisterVariable(&r_equalize_entities_to);
7177         Cvar_RegisterVariable(&r_depthfirst);
7178         Cvar_RegisterVariable(&r_useinfinitefarclip);
7179         Cvar_RegisterVariable(&r_farclip_base);
7180         Cvar_RegisterVariable(&r_farclip_world);
7181         Cvar_RegisterVariable(&r_nearclip);
7182         Cvar_RegisterVariable(&r_showbboxes);
7183         Cvar_RegisterVariable(&r_showsurfaces);
7184         Cvar_RegisterVariable(&r_showtris);
7185         Cvar_RegisterVariable(&r_shownormals);
7186         Cvar_RegisterVariable(&r_showlighting);
7187         Cvar_RegisterVariable(&r_showshadowvolumes);
7188         Cvar_RegisterVariable(&r_showcollisionbrushes);
7189         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7190         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7191         Cvar_RegisterVariable(&r_showdisabledepthtest);
7192         Cvar_RegisterVariable(&r_drawportals);
7193         Cvar_RegisterVariable(&r_drawentities);
7194         Cvar_RegisterVariable(&r_draw2d);
7195         Cvar_RegisterVariable(&r_drawworld);
7196         Cvar_RegisterVariable(&r_cullentities_trace);
7197         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7198         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7199         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7200         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7201         Cvar_RegisterVariable(&r_drawviewmodel);
7202         Cvar_RegisterVariable(&r_drawexteriormodel);
7203         Cvar_RegisterVariable(&r_speeds);
7204         Cvar_RegisterVariable(&r_fullbrights);
7205         Cvar_RegisterVariable(&r_wateralpha);
7206         Cvar_RegisterVariable(&r_dynamic);
7207         Cvar_RegisterVariable(&r_fullbright);
7208         Cvar_RegisterVariable(&r_shadows);
7209         Cvar_RegisterVariable(&r_shadows_darken);
7210         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7211         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7212         Cvar_RegisterVariable(&r_shadows_throwdistance);
7213         Cvar_RegisterVariable(&r_shadows_throwdirection);
7214         Cvar_RegisterVariable(&r_shadows_focus);
7215         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7216         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7217         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7218         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7219         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7220         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7221         Cvar_RegisterVariable(&r_fog_exp2);
7222         Cvar_RegisterVariable(&r_drawfog);
7223         Cvar_RegisterVariable(&r_transparentdepthmasking);
7224         Cvar_RegisterVariable(&r_texture_dds_load);
7225         Cvar_RegisterVariable(&r_texture_dds_save);
7226         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7227         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7228         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7229         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7230         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7231         Cvar_RegisterVariable(&r_textureunits);
7232         Cvar_RegisterVariable(&gl_combine);
7233         Cvar_RegisterVariable(&r_glsl);
7234         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7235         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7236         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7237         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7238         Cvar_RegisterVariable(&r_glsl_postprocess);
7239         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7240         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7241         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7243         Cvar_RegisterVariable(&r_water);
7244         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7245         Cvar_RegisterVariable(&r_water_clippingplanebias);
7246         Cvar_RegisterVariable(&r_water_refractdistort);
7247         Cvar_RegisterVariable(&r_water_reflectdistort);
7248         Cvar_RegisterVariable(&r_lerpsprites);
7249         Cvar_RegisterVariable(&r_lerpmodels);
7250         Cvar_RegisterVariable(&r_lerplightstyles);
7251         Cvar_RegisterVariable(&r_waterscroll);
7252         Cvar_RegisterVariable(&r_bloom);
7253         Cvar_RegisterVariable(&r_bloom_colorscale);
7254         Cvar_RegisterVariable(&r_bloom_brighten);
7255         Cvar_RegisterVariable(&r_bloom_blur);
7256         Cvar_RegisterVariable(&r_bloom_resolution);
7257         Cvar_RegisterVariable(&r_bloom_colorexponent);
7258         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7259         Cvar_RegisterVariable(&r_hdr);
7260         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7261         Cvar_RegisterVariable(&r_hdr_glowintensity);
7262         Cvar_RegisterVariable(&r_hdr_range);
7263         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7264         Cvar_RegisterVariable(&developer_texturelogging);
7265         Cvar_RegisterVariable(&gl_lightmaps);
7266         Cvar_RegisterVariable(&r_test);
7267         Cvar_RegisterVariable(&r_glsl_saturation);
7268         Cvar_RegisterVariable(&r_framedatasize);
7269         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7270                 Cvar_SetValue("r_fullbrights", 0);
7271         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7272
7273         Cvar_RegisterVariable(&r_track_sprites);
7274         Cvar_RegisterVariable(&r_track_sprites_flags);
7275         Cvar_RegisterVariable(&r_track_sprites_scalew);
7276         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7277         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7278         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7279 }
7280
7281 extern void R_Textures_Init(void);
7282 extern void GL_Draw_Init(void);
7283 extern void GL_Main_Init(void);
7284 extern void R_Shadow_Init(void);
7285 extern void R_Sky_Init(void);
7286 extern void GL_Surf_Init(void);
7287 extern void R_Particles_Init(void);
7288 extern void R_Explosion_Init(void);
7289 extern void gl_backend_init(void);
7290 extern void Sbar_Init(void);
7291 extern void R_LightningBeams_Init(void);
7292 extern void Mod_RenderInit(void);
7293 extern void Font_Init(void);
7294
7295 void Render_Init(void)
7296 {
7297         gl_backend_init();
7298         R_Textures_Init();
7299         GL_Main_Init();
7300         Font_Init();
7301         GL_Draw_Init();
7302         R_Shadow_Init();
7303         R_Sky_Init();
7304         GL_Surf_Init();
7305         Sbar_Init();
7306         R_Particles_Init();
7307         R_Explosion_Init();
7308         R_LightningBeams_Init();
7309         Mod_RenderInit();
7310 }
7311
7312 /*
7313 ===============
7314 GL_Init
7315 ===============
7316 */
7317 extern char *ENGINE_EXTENSIONS;
7318 void GL_Init (void)
7319 {
7320         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7321         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7322         gl_version = (const char *)qglGetString(GL_VERSION);
7323         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7324
7325         if (!gl_extensions)
7326                 gl_extensions = "";
7327         if (!gl_platformextensions)
7328                 gl_platformextensions = "";
7329
7330         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7331         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7332         Con_Printf("GL_VERSION: %s\n", gl_version);
7333         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7334         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7335
7336         VID_CheckExtensions();
7337
7338         // LordHavoc: report supported extensions
7339         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7340
7341         // clear to black (loading plaque will be seen over this)
7342         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7343 }
7344
7345 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7346 {
7347         int i;
7348         mplane_t *p;
7349         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7350         {
7351                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7352                 if (i == 4)
7353                         continue;
7354                 p = r_refdef.view.frustum + i;
7355                 switch(p->signbits)
7356                 {
7357                 default:
7358                 case 0:
7359                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7360                                 return true;
7361                         break;
7362                 case 1:
7363                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7364                                 return true;
7365                         break;
7366                 case 2:
7367                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7368                                 return true;
7369                         break;
7370                 case 3:
7371                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7372                                 return true;
7373                         break;
7374                 case 4:
7375                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7376                                 return true;
7377                         break;
7378                 case 5:
7379                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7380                                 return true;
7381                         break;
7382                 case 6:
7383                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7384                                 return true;
7385                         break;
7386                 case 7:
7387                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7388                                 return true;
7389                         break;
7390                 }
7391         }
7392         return false;
7393 }
7394
7395 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7396 {
7397         int i;
7398         const mplane_t *p;
7399         for (i = 0;i < numplanes;i++)
7400         {
7401                 p = planes + i;
7402                 switch(p->signbits)
7403                 {
7404                 default:
7405                 case 0:
7406                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7407                                 return true;
7408                         break;
7409                 case 1:
7410                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7411                                 return true;
7412                         break;
7413                 case 2:
7414                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7415                                 return true;
7416                         break;
7417                 case 3:
7418                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7419                                 return true;
7420                         break;
7421                 case 4:
7422                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7423                                 return true;
7424                         break;
7425                 case 5:
7426                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7427                                 return true;
7428                         break;
7429                 case 6:
7430                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7431                                 return true;
7432                         break;
7433                 case 7:
7434                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7435                                 return true;
7436                         break;
7437                 }
7438         }
7439         return false;
7440 }
7441
7442 //==================================================================================
7443
7444 // LordHavoc: this stores temporary data used within the same frame
7445
7446 qboolean r_framedata_failed;
7447 static size_t r_framedata_size;
7448 static size_t r_framedata_current;
7449 static void *r_framedata_base;
7450
7451 void R_FrameData_Reset(void)
7452 {
7453         if (r_framedata_base)
7454                 Mem_Free(r_framedata_base);
7455         r_framedata_base = NULL;
7456         r_framedata_size = 0;
7457         r_framedata_current = 0;
7458         r_framedata_failed = false;
7459 }
7460
7461 void R_FrameData_NewFrame(void)
7462 {
7463         size_t wantedsize;
7464         if (r_framedata_failed)
7465                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7466         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7467         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7468         if (r_framedata_size != wantedsize)
7469         {
7470                 r_framedata_size = wantedsize;
7471                 if (r_framedata_base)
7472                         Mem_Free(r_framedata_base);
7473                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7474         }
7475         r_framedata_current = 0;
7476         r_framedata_failed = false;
7477 }
7478
7479 void *R_FrameData_Alloc(size_t size)
7480 {
7481         void *data;
7482
7483         // align to 16 byte boundary
7484         size = (size + 15) & ~15;
7485         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7486         r_framedata_current += size;
7487
7488         // check overflow
7489         if (r_framedata_current > r_framedata_size)
7490                 r_framedata_failed = true;
7491
7492         // return NULL on everything after a failure
7493         if (r_framedata_failed)
7494                 return NULL;
7495
7496         return data;
7497 }
7498
7499 void *R_FrameData_Store(size_t size, void *data)
7500 {
7501         void *d = R_FrameData_Alloc(size);
7502         if (d)
7503                 memcpy(d, data, size);
7504         return d;
7505 }
7506
7507 //==================================================================================
7508
7509 // LordHavoc: animcache originally written by Echon, rewritten since then
7510
7511 /**
7512  * Animation cache prevents re-generating mesh data for an animated model
7513  * multiple times in one frame for lighting, shadowing, reflections, etc.
7514  */
7515
7516 void R_AnimCache_Free(void)
7517 {
7518 }
7519
7520 void R_AnimCache_ClearCache(void)
7521 {
7522         int i;
7523         entity_render_t *ent;
7524
7525         for (i = 0;i < r_refdef.scene.numentities;i++)
7526         {
7527                 ent = r_refdef.scene.entities[i];
7528                 ent->animcache_vertex3f = NULL;
7529                 ent->animcache_normal3f = NULL;
7530                 ent->animcache_svector3f = NULL;
7531                 ent->animcache_tvector3f = NULL;
7532                 ent->animcache_vertexposition = NULL;
7533                 ent->animcache_vertexmesh = NULL;
7534                 ent->animcache_vertexpositionbuffer = NULL;
7535                 ent->animcache_vertexmeshbuffer = NULL;
7536         }
7537 }
7538
7539 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7540 {
7541         int i;
7542
7543         // identical memory layout, so no need to allocate...
7544         // this also provides the vertexposition structure to everything, e.g.
7545         // depth masked rendering currently uses it even if having separate
7546         // arrays
7547         // NOTE: get rid of this optimization if changing it to e.g. 4f
7548         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7549
7550         // TODO:
7551         // get rid of following uses of VERTEXPOSITION, change to the array:
7552         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7553         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7554         // R_DrawTextureSurfaceList_DepthOnly
7555         // R_Q1BSP_DrawShadowMap
7556
7557         switch(vid.renderpath)
7558         {
7559         case RENDERPATH_GL20:
7560         case RENDERPATH_CGGL:
7561                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7562                 if (gl_mesh_separatearrays.integer)
7563                         return;
7564                 break;
7565         case RENDERPATH_D3D9:
7566         case RENDERPATH_D3D10:
7567         case RENDERPATH_D3D11:
7568                 // always need the meshbuffers
7569                 break;
7570         case RENDERPATH_GL13:
7571         case RENDERPATH_GL11:
7572                 // never need the meshbuffers
7573                 return;
7574         }
7575
7576         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7577                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7578         /*
7579         if (!ent->animcache_vertexposition)
7580                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7581         */
7582         if (ent->animcache_vertexposition)
7583         {
7584                 /*
7585                 for (i = 0;i < numvertices;i++)
7586                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7587                 */
7588                 // TODO: upload vertex buffer?
7589         }
7590         if (ent->animcache_vertexmesh)
7591         {
7592                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7593                 for (i = 0;i < numvertices;i++)
7594                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7595                 if (ent->animcache_svector3f)
7596                         for (i = 0;i < numvertices;i++)
7597                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7598                 if (ent->animcache_tvector3f)
7599                         for (i = 0;i < numvertices;i++)
7600                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7601                 if (ent->animcache_normal3f)
7602                         for (i = 0;i < numvertices;i++)
7603                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7604                 // TODO: upload vertex buffer?
7605         }
7606 }
7607
7608 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7609 {
7610         dp_model_t *model = ent->model;
7611         int numvertices;
7612         // see if it's already cached this frame
7613         if (ent->animcache_vertex3f)
7614         {
7615                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7616                 if (wantnormals || wanttangents)
7617                 {
7618                         if (ent->animcache_normal3f)
7619                                 wantnormals = false;
7620                         if (ent->animcache_svector3f)
7621                                 wanttangents = false;
7622                         if (wantnormals || wanttangents)
7623                         {
7624                                 numvertices = model->surfmesh.num_vertices;
7625                                 if (wantnormals)
7626                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7627                                 if (wanttangents)
7628                                 {
7629                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7630                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7631                                 }
7632                                 if (!r_framedata_failed)
7633                                 {
7634                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7635                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7636                                 }
7637                         }
7638                 }
7639         }
7640         else
7641         {
7642                 // see if this ent is worth caching
7643                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7644                         return false;
7645                 // get some memory for this entity and generate mesh data
7646                 numvertices = model->surfmesh.num_vertices;
7647                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7648                 if (wantnormals)
7649                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7650                 if (wanttangents)
7651                 {
7652                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7653                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7654                 }
7655                 if (!r_framedata_failed)
7656                 {
7657                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7658                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7659                 }
7660         }
7661         return !r_framedata_failed;
7662 }
7663
7664 void R_AnimCache_CacheVisibleEntities(void)
7665 {
7666         int i;
7667         qboolean wantnormals = true;
7668         qboolean wanttangents = !r_showsurfaces.integer;
7669
7670         switch(vid.renderpath)
7671         {
7672         case RENDERPATH_GL20:
7673         case RENDERPATH_CGGL:
7674         case RENDERPATH_D3D9:
7675         case RENDERPATH_D3D10:
7676         case RENDERPATH_D3D11:
7677                 break;
7678         case RENDERPATH_GL13:
7679         case RENDERPATH_GL11:
7680                 wanttangents = false;
7681                 break;
7682         }
7683
7684         if (r_shownormals.integer)
7685                 wanttangents = wantnormals = true;
7686
7687         // TODO: thread this
7688         // NOTE: R_PrepareRTLights() also caches entities
7689
7690         for (i = 0;i < r_refdef.scene.numentities;i++)
7691                 if (r_refdef.viewcache.entityvisible[i])
7692                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7693 }
7694
7695 //==================================================================================
7696
7697 static void R_View_UpdateEntityLighting (void)
7698 {
7699         int i;
7700         entity_render_t *ent;
7701         vec3_t tempdiffusenormal, avg;
7702         vec_t f, fa, fd, fdd;
7703         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7704
7705         for (i = 0;i < r_refdef.scene.numentities;i++)
7706         {
7707                 ent = r_refdef.scene.entities[i];
7708
7709                 // skip unseen models
7710                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7711                         continue;
7712
7713                 // skip bsp models
7714                 if (ent->model && ent->model->brush.num_leafs)
7715                 {
7716                         // TODO: use modellight for r_ambient settings on world?
7717                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7718                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7719                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7720                         continue;
7721                 }
7722
7723                 // fetch the lighting from the worldmodel data
7724                 VectorClear(ent->modellight_ambient);
7725                 VectorClear(ent->modellight_diffuse);
7726                 VectorClear(tempdiffusenormal);
7727                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7728                 {
7729                         vec3_t org;
7730                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7731                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7732                         if(ent->flags & RENDER_EQUALIZE)
7733                         {
7734                                 // first fix up ambient lighting...
7735                                 if(r_equalize_entities_minambient.value > 0)
7736                                 {
7737                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7738                                         if(fd > 0)
7739                                         {
7740                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7741                                                 if(fa < r_equalize_entities_minambient.value * fd)
7742                                                 {
7743                                                         // solve:
7744                                                         //   fa'/fd' = minambient
7745                                                         //   fa'+0.25*fd' = fa+0.25*fd
7746                                                         //   ...
7747                                                         //   fa' = fd' * minambient
7748                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7749                                                         //   ...
7750                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7751                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7752                                                         //   ...
7753                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7754                                                         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
7755                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7756                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7757                                                 }
7758                                         }
7759                                 }
7760
7761                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7762                                 {
7763                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7764                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7765                                         if(f > 0)
7766                                         {
7767                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7768                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7769                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7770                                         }
7771                                 }
7772                         }
7773                 }
7774                 else // highly rare
7775                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7776
7777                 // move the light direction into modelspace coordinates for lighting code
7778                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7779                 if(VectorLength2(ent->modellight_lightdir) == 0)
7780                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7781                 VectorNormalize(ent->modellight_lightdir);
7782         }
7783 }
7784
7785 #define MAX_LINEOFSIGHTTRACES 64
7786
7787 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7788 {
7789         int i;
7790         vec3_t boxmins, boxmaxs;
7791         vec3_t start;
7792         vec3_t end;
7793         dp_model_t *model = r_refdef.scene.worldmodel;
7794
7795         if (!model || !model->brush.TraceLineOfSight)
7796                 return true;
7797
7798         // expand the box a little
7799         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7800         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7801         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7802         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7803         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7804         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7805
7806         // return true if eye is inside enlarged box
7807         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7808                 return true;
7809
7810         // try center
7811         VectorCopy(eye, start);
7812         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7813         if (model->brush.TraceLineOfSight(model, start, end))
7814                 return true;
7815
7816         // try various random positions
7817         for (i = 0;i < numsamples;i++)
7818         {
7819                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7820                 if (model->brush.TraceLineOfSight(model, start, end))
7821                         return true;
7822         }
7823
7824         return false;
7825 }
7826
7827
7828 static void R_View_UpdateEntityVisible (void)
7829 {
7830         int i;
7831         int renderimask;
7832         int samples;
7833         entity_render_t *ent;
7834
7835         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7836                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7837                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7838                 :                                                          RENDER_EXTERIORMODEL;
7839         if (!r_drawviewmodel.integer)
7840                 renderimask |= RENDER_VIEWMODEL;
7841         if (!r_drawexteriormodel.integer)
7842                 renderimask |= RENDER_EXTERIORMODEL;
7843         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7844         {
7845                 // worldmodel can check visibility
7846                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7847                 for (i = 0;i < r_refdef.scene.numentities;i++)
7848                 {
7849                         ent = r_refdef.scene.entities[i];
7850                         if (!(ent->flags & renderimask))
7851                         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)))
7852                         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))
7853                                 r_refdef.viewcache.entityvisible[i] = true;
7854                 }
7855                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7856                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7857                 {
7858                         for (i = 0;i < r_refdef.scene.numentities;i++)
7859                         {
7860                                 ent = r_refdef.scene.entities[i];
7861                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7862                                 {
7863                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7864                                         if (samples < 0)
7865                                                 continue; // temp entities do pvs only
7866                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7867                                                 ent->last_trace_visibility = realtime;
7868                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7869                                                 r_refdef.viewcache.entityvisible[i] = 0;
7870                                 }
7871                         }
7872                 }
7873         }
7874         else
7875         {
7876                 // no worldmodel or it can't check visibility
7877                 for (i = 0;i < r_refdef.scene.numentities;i++)
7878                 {
7879                         ent = r_refdef.scene.entities[i];
7880                         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));
7881                 }
7882         }
7883 }
7884
7885 /// only used if skyrendermasked, and normally returns false
7886 int R_DrawBrushModelsSky (void)
7887 {
7888         int i, sky;
7889         entity_render_t *ent;
7890
7891         sky = false;
7892         for (i = 0;i < r_refdef.scene.numentities;i++)
7893         {
7894                 if (!r_refdef.viewcache.entityvisible[i])
7895                         continue;
7896                 ent = r_refdef.scene.entities[i];
7897                 if (!ent->model || !ent->model->DrawSky)
7898                         continue;
7899                 ent->model->DrawSky(ent);
7900                 sky = true;
7901         }
7902         return sky;
7903 }
7904
7905 static void R_DrawNoModel(entity_render_t *ent);
7906 static void R_DrawModels(void)
7907 {
7908         int i;
7909         entity_render_t *ent;
7910
7911         for (i = 0;i < r_refdef.scene.numentities;i++)
7912         {
7913                 if (!r_refdef.viewcache.entityvisible[i])
7914                         continue;
7915                 ent = r_refdef.scene.entities[i];
7916                 r_refdef.stats.entities++;
7917                 if (ent->model && ent->model->Draw != NULL)
7918                         ent->model->Draw(ent);
7919                 else
7920                         R_DrawNoModel(ent);
7921         }
7922 }
7923
7924 static void R_DrawModelsDepth(void)
7925 {
7926         int i;
7927         entity_render_t *ent;
7928
7929         for (i = 0;i < r_refdef.scene.numentities;i++)
7930         {
7931                 if (!r_refdef.viewcache.entityvisible[i])
7932                         continue;
7933                 ent = r_refdef.scene.entities[i];
7934                 if (ent->model && ent->model->DrawDepth != NULL)
7935                         ent->model->DrawDepth(ent);
7936         }
7937 }
7938
7939 static void R_DrawModelsDebug(void)
7940 {
7941         int i;
7942         entity_render_t *ent;
7943
7944         for (i = 0;i < r_refdef.scene.numentities;i++)
7945         {
7946                 if (!r_refdef.viewcache.entityvisible[i])
7947                         continue;
7948                 ent = r_refdef.scene.entities[i];
7949                 if (ent->model && ent->model->DrawDebug != NULL)
7950                         ent->model->DrawDebug(ent);
7951         }
7952 }
7953
7954 static void R_DrawModelsAddWaterPlanes(void)
7955 {
7956         int i;
7957         entity_render_t *ent;
7958
7959         for (i = 0;i < r_refdef.scene.numentities;i++)
7960         {
7961                 if (!r_refdef.viewcache.entityvisible[i])
7962                         continue;
7963                 ent = r_refdef.scene.entities[i];
7964                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7965                         ent->model->DrawAddWaterPlanes(ent);
7966         }
7967 }
7968
7969 static void R_View_SetFrustum(void)
7970 {
7971         int i;
7972         double slopex, slopey;
7973         vec3_t forward, left, up, origin;
7974
7975         // we can't trust r_refdef.view.forward and friends in reflected scenes
7976         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7977
7978 #if 0
7979         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7980         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7981         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7982         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7983         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7984         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7985         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7986         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7987         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7988         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7989         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7990         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7991 #endif
7992
7993 #if 0
7994         zNear = r_refdef.nearclip;
7995         nudge = 1.0 - 1.0 / (1<<23);
7996         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7997         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7998         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7999         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8000         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8001         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8002         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8003         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8004 #endif
8005
8006
8007
8008 #if 0
8009         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8010         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8011         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8012         r_refdef.view.frustum[0].dist = m[15] - m[12];
8013
8014         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8015         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8016         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8017         r_refdef.view.frustum[1].dist = m[15] + m[12];
8018
8019         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8020         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8021         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8022         r_refdef.view.frustum[2].dist = m[15] - m[13];
8023
8024         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8025         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8026         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8027         r_refdef.view.frustum[3].dist = m[15] + m[13];
8028
8029         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8030         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8031         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8032         r_refdef.view.frustum[4].dist = m[15] - m[14];
8033
8034         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8035         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8036         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8037         r_refdef.view.frustum[5].dist = m[15] + m[14];
8038 #endif
8039
8040         if (r_refdef.view.useperspective)
8041         {
8042                 slopex = 1.0 / r_refdef.view.frustum_x;
8043                 slopey = 1.0 / r_refdef.view.frustum_y;
8044                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8045                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8046                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8047                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8048                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8049
8050                 // Leaving those out was a mistake, those were in the old code, and they
8051                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8052                 // I couldn't reproduce it after adding those normalizations. --blub
8053                 VectorNormalize(r_refdef.view.frustum[0].normal);
8054                 VectorNormalize(r_refdef.view.frustum[1].normal);
8055                 VectorNormalize(r_refdef.view.frustum[2].normal);
8056                 VectorNormalize(r_refdef.view.frustum[3].normal);
8057
8058                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8059                 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]);
8060                 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]);
8061                 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]);
8062                 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]);
8063
8064                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8065                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8066                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8067                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8068                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8069         }
8070         else
8071         {
8072                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8073                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8074                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8075                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8076                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8077                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8078                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8079                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8080                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8081                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8082         }
8083         r_refdef.view.numfrustumplanes = 5;
8084
8085         if (r_refdef.view.useclipplane)
8086         {
8087                 r_refdef.view.numfrustumplanes = 6;
8088                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8089         }
8090
8091         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8092                 PlaneClassify(r_refdef.view.frustum + i);
8093
8094         // LordHavoc: note to all quake engine coders, Quake had a special case
8095         // for 90 degrees which assumed a square view (wrong), so I removed it,
8096         // Quake2 has it disabled as well.
8097
8098         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8099         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8100         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8101         //PlaneClassify(&frustum[0]);
8102
8103         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8104         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8105         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8106         //PlaneClassify(&frustum[1]);
8107
8108         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8109         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8110         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8111         //PlaneClassify(&frustum[2]);
8112
8113         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8114         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8115         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8116         //PlaneClassify(&frustum[3]);
8117
8118         // nearclip plane
8119         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8120         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8121         //PlaneClassify(&frustum[4]);
8122 }
8123
8124 void R_View_Update(void)
8125 {
8126         R_Main_ResizeViewCache();
8127         R_View_SetFrustum();
8128         R_View_WorldVisibility(r_refdef.view.useclipplane);
8129         R_View_UpdateEntityVisible();
8130         R_View_UpdateEntityLighting();
8131 }
8132
8133 void R_SetupView(qboolean allowwaterclippingplane)
8134 {
8135         const float *customclipplane = NULL;
8136         float plane[4];
8137         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8138         {
8139                 // LordHavoc: couldn't figure out how to make this approach the
8140                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8141                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8142                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8143                         dist = r_refdef.view.clipplane.dist;
8144                 plane[0] = r_refdef.view.clipplane.normal[0];
8145                 plane[1] = r_refdef.view.clipplane.normal[1];
8146                 plane[2] = r_refdef.view.clipplane.normal[2];
8147                 plane[3] = dist;
8148                 customclipplane = plane;
8149         }
8150
8151         if (!r_refdef.view.useperspective)
8152                 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);
8153         else if (vid.stencil && r_useinfinitefarclip.integer)
8154                 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);
8155         else
8156                 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);
8157         R_SetViewport(&r_refdef.view.viewport);
8158 }
8159
8160 void R_EntityMatrix(const matrix4x4_t *matrix)
8161 {
8162         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8163         {
8164                 gl_modelmatrixchanged = false;
8165                 gl_modelmatrix = *matrix;
8166                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8167                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8168                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8169                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8170                 CHECKGLERROR
8171                 switch(vid.renderpath)
8172                 {
8173                 case RENDERPATH_D3D9:
8174 #ifdef SUPPORTD3D
8175                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8176                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8177 #endif
8178                         break;
8179                 case RENDERPATH_D3D10:
8180                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8181                         break;
8182                 case RENDERPATH_D3D11:
8183                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8184                         break;
8185                 case RENDERPATH_GL20:
8186                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8187                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8188                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8189                         break;
8190                 case RENDERPATH_CGGL:
8191 #ifdef SUPPORTCG
8192                         CHECKCGERROR
8193                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8194                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8195                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8196 #endif
8197                         break;
8198                 case RENDERPATH_GL13:
8199                 case RENDERPATH_GL11:
8200                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8201                         break;
8202                 }
8203         }
8204 }
8205
8206 void R_ResetViewRendering2D(void)
8207 {
8208         r_viewport_t viewport;
8209         DrawQ_Finish();
8210
8211         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8212         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);
8213         R_SetViewport(&viewport);
8214         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8215         GL_Color(1, 1, 1, 1);
8216         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8217         GL_BlendFunc(GL_ONE, GL_ZERO);
8218         GL_AlphaTest(false);
8219         GL_ScissorTest(false);
8220         GL_DepthMask(false);
8221         GL_DepthRange(0, 1);
8222         GL_DepthTest(false);
8223         GL_DepthFunc(GL_LEQUAL);
8224         R_EntityMatrix(&identitymatrix);
8225         R_Mesh_ResetTextureState();
8226         GL_PolygonOffset(0, 0);
8227         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8228         switch(vid.renderpath)
8229         {
8230         case RENDERPATH_GL11:
8231         case RENDERPATH_GL13:
8232         case RENDERPATH_GL20:
8233         case RENDERPATH_CGGL:
8234                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8235                 break;
8236         case RENDERPATH_D3D9:
8237         case RENDERPATH_D3D10:
8238         case RENDERPATH_D3D11:
8239                 break;
8240         }
8241         GL_CullFace(GL_NONE);
8242 }
8243
8244 void R_ResetViewRendering3D(void)
8245 {
8246         DrawQ_Finish();
8247
8248         R_SetupView(true);
8249         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8250         GL_Color(1, 1, 1, 1);
8251         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8252         GL_BlendFunc(GL_ONE, GL_ZERO);
8253         GL_AlphaTest(false);
8254         GL_ScissorTest(true);
8255         GL_DepthMask(true);
8256         GL_DepthRange(0, 1);
8257         GL_DepthTest(true);
8258         GL_DepthFunc(GL_LEQUAL);
8259         R_EntityMatrix(&identitymatrix);
8260         R_Mesh_ResetTextureState();
8261         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8262         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8263         switch(vid.renderpath)
8264         {
8265         case RENDERPATH_GL11:
8266         case RENDERPATH_GL13:
8267         case RENDERPATH_GL20:
8268         case RENDERPATH_CGGL:
8269                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8270                 break;
8271         case RENDERPATH_D3D9:
8272         case RENDERPATH_D3D10:
8273         case RENDERPATH_D3D11:
8274                 break;
8275         }
8276         GL_CullFace(r_refdef.view.cullface_back);
8277 }
8278
8279 /*
8280 ================
8281 R_RenderView_UpdateViewVectors
8282 ================
8283 */
8284 static void R_RenderView_UpdateViewVectors(void)
8285 {
8286         // break apart the view matrix into vectors for various purposes
8287         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8288         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8289         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8290         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8291         // make an inverted copy of the view matrix for tracking sprites
8292         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8293 }
8294
8295 void R_RenderScene(void);
8296 void R_RenderWaterPlanes(void);
8297
8298 static void R_Water_StartFrame(void)
8299 {
8300         int i;
8301         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8302         r_waterstate_waterplane_t *p;
8303
8304         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8305                 return;
8306
8307         switch(vid.renderpath)
8308         {
8309         case RENDERPATH_GL20:
8310         case RENDERPATH_CGGL:
8311         case RENDERPATH_D3D9:
8312         case RENDERPATH_D3D10:
8313         case RENDERPATH_D3D11:
8314                 break;
8315         case RENDERPATH_GL13:
8316         case RENDERPATH_GL11:
8317                 return;
8318         }
8319
8320         // set waterwidth and waterheight to the water resolution that will be
8321         // used (often less than the screen resolution for faster rendering)
8322         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8323         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8324
8325         // calculate desired texture sizes
8326         // can't use water if the card does not support the texture size
8327         if (!r_water.integer || r_showsurfaces.integer)
8328                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8329         else if (vid.support.arb_texture_non_power_of_two)
8330         {
8331                 texturewidth = waterwidth;
8332                 textureheight = waterheight;
8333                 camerawidth = waterwidth;
8334                 cameraheight = waterheight;
8335         }
8336         else
8337         {
8338                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8339                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8340                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8341                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8342         }
8343
8344         // allocate textures as needed
8345         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8346         {
8347                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8348                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8349                 {
8350                         if (p->texture_refraction)
8351                                 R_FreeTexture(p->texture_refraction);
8352                         p->texture_refraction = NULL;
8353                         if (p->texture_reflection)
8354                                 R_FreeTexture(p->texture_reflection);
8355                         p->texture_reflection = NULL;
8356                         if (p->texture_camera)
8357                                 R_FreeTexture(p->texture_camera);
8358                         p->texture_camera = NULL;
8359                 }
8360                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8361                 r_waterstate.texturewidth = texturewidth;
8362                 r_waterstate.textureheight = textureheight;
8363                 r_waterstate.camerawidth = camerawidth;
8364                 r_waterstate.cameraheight = cameraheight;
8365         }
8366
8367         if (r_waterstate.texturewidth)
8368         {
8369                 r_waterstate.enabled = true;
8370
8371                 // when doing a reduced render (HDR) we want to use a smaller area
8372                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8373                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8374
8375                 // set up variables that will be used in shader setup
8376                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8377                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8378                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8379                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8380         }
8381
8382         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8383         r_waterstate.numwaterplanes = 0;
8384 }
8385
8386 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8387 {
8388         int triangleindex, planeindex;
8389         const int *e;
8390         vec3_t vert[3];
8391         vec3_t normal;
8392         vec3_t center;
8393         mplane_t plane;
8394         r_waterstate_waterplane_t *p;
8395         texture_t *t = R_GetCurrentTexture(surface->texture);
8396
8397         // just use the first triangle with a valid normal for any decisions
8398         VectorClear(normal);
8399         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8400         {
8401                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8402                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8403                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8404                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8405                 if (VectorLength2(normal) >= 0.001)
8406                         break;
8407         }
8408
8409         VectorCopy(normal, plane.normal);
8410         VectorNormalize(plane.normal);
8411         plane.dist = DotProduct(vert[0], plane.normal);
8412         PlaneClassify(&plane);
8413         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8414         {
8415                 // skip backfaces (except if nocullface is set)
8416                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8417                         return;
8418                 VectorNegate(plane.normal, plane.normal);
8419                 plane.dist *= -1;
8420                 PlaneClassify(&plane);
8421         }
8422
8423
8424         // find a matching plane if there is one
8425         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8426                 if(p->camera_entity == t->camera_entity)
8427                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8428                                 break;
8429         if (planeindex >= r_waterstate.maxwaterplanes)
8430                 return; // nothing we can do, out of planes
8431
8432         // if this triangle does not fit any known plane rendered this frame, add one
8433         if (planeindex >= r_waterstate.numwaterplanes)
8434         {
8435                 // store the new plane
8436                 r_waterstate.numwaterplanes++;
8437                 p->plane = plane;
8438                 // clear materialflags and pvs
8439                 p->materialflags = 0;
8440                 p->pvsvalid = false;
8441                 p->camera_entity = t->camera_entity;
8442         }
8443         // merge this surface's materialflags into the waterplane
8444         p->materialflags |= t->currentmaterialflags;
8445         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8446         {
8447                 // merge this surface's PVS into the waterplane
8448                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8449                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8450                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8451                 {
8452                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8453                         p->pvsvalid = true;
8454                 }
8455         }
8456 }
8457
8458 static void R_Water_ProcessPlanes(void)
8459 {
8460         r_refdef_view_t originalview;
8461         r_refdef_view_t myview;
8462         int planeindex;
8463         r_waterstate_waterplane_t *p;
8464         vec3_t visorigin;
8465
8466         originalview = r_refdef.view;
8467
8468         // make sure enough textures are allocated
8469         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8470         {
8471                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8472                 {
8473                         if (!p->texture_refraction)
8474                                 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);
8475                         if (!p->texture_refraction)
8476                                 goto error;
8477                 }
8478                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8479                 {
8480                         if (!p->texture_camera)
8481                                 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);
8482                         if (!p->texture_camera)
8483                                 goto error;
8484                 }
8485
8486                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8487                 {
8488                         if (!p->texture_reflection)
8489                                 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);
8490                         if (!p->texture_reflection)
8491                                 goto error;
8492                 }
8493         }
8494
8495         // render views
8496         r_refdef.view = originalview;
8497         r_refdef.view.showdebug = false;
8498         r_refdef.view.width = r_waterstate.waterwidth;
8499         r_refdef.view.height = r_waterstate.waterheight;
8500         r_refdef.view.useclipplane = true;
8501         myview = r_refdef.view;
8502         r_waterstate.renderingscene = true;
8503         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8504         {
8505                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8506                 {
8507                         r_refdef.view = myview;
8508                         // render reflected scene and copy into texture
8509                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8510                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8511                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8512                         r_refdef.view.clipplane = p->plane;
8513                         // reverse the cullface settings for this render
8514                         r_refdef.view.cullface_front = GL_FRONT;
8515                         r_refdef.view.cullface_back = GL_BACK;
8516                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8517                         {
8518                                 r_refdef.view.usecustompvs = true;
8519                                 if (p->pvsvalid)
8520                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8521                                 else
8522                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8523                         }
8524
8525                         R_ResetViewRendering3D();
8526                         R_ClearScreen(r_refdef.fogenabled);
8527                         R_View_Update();
8528                         R_RenderScene();
8529
8530                         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);
8531                 }
8532
8533                 // render the normal view scene and copy into texture
8534                 // (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)
8535                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8536                 {
8537                         r_waterstate.renderingrefraction = true;
8538                         r_refdef.view = myview;
8539
8540                         r_refdef.view.clipplane = p->plane;
8541                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8542                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8543
8544                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8545                         {
8546                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8547                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8548                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8549                                 R_RenderView_UpdateViewVectors();
8550                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8551                                 {
8552                                         r_refdef.view.usecustompvs = true;
8553                                         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);
8554                                 }
8555                         }
8556
8557                         PlaneClassify(&r_refdef.view.clipplane);
8558
8559                         R_ResetViewRendering3D();
8560                         R_ClearScreen(r_refdef.fogenabled);
8561                         R_View_Update();
8562                         R_RenderScene();
8563
8564                         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);
8565                         r_waterstate.renderingrefraction = false;
8566                 }
8567                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8568                 {
8569                         r_refdef.view = myview;
8570
8571                         r_refdef.view.clipplane = p->plane;
8572                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8573                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8574
8575                         r_refdef.view.width = r_waterstate.camerawidth;
8576                         r_refdef.view.height = r_waterstate.cameraheight;
8577                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8578                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8579
8580                         if(p->camera_entity)
8581                         {
8582                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8583                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8584                         }
8585
8586                         // reverse the cullface settings for this render
8587                         r_refdef.view.cullface_front = GL_FRONT;
8588                         r_refdef.view.cullface_back = GL_BACK;
8589                         // also reverse the view matrix
8590                         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
8591                         R_RenderView_UpdateViewVectors();
8592                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8593                         {
8594                                 r_refdef.view.usecustompvs = true;
8595                                 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);
8596                         }
8597                         
8598                         // camera needs no clipplane
8599                         r_refdef.view.useclipplane = false;
8600
8601                         PlaneClassify(&r_refdef.view.clipplane);
8602
8603                         R_ResetViewRendering3D();
8604                         R_ClearScreen(r_refdef.fogenabled);
8605                         R_View_Update();
8606                         R_RenderScene();
8607
8608                         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);
8609                         r_waterstate.renderingrefraction = false;
8610                 }
8611
8612         }
8613         r_waterstate.renderingscene = false;
8614         r_refdef.view = originalview;
8615         R_ResetViewRendering3D();
8616         R_ClearScreen(r_refdef.fogenabled);
8617         R_View_Update();
8618         return;
8619 error:
8620         r_refdef.view = originalview;
8621         r_waterstate.renderingscene = false;
8622         Cvar_SetValueQuick(&r_water, 0);
8623         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8624         return;
8625 }
8626
8627 void R_Bloom_StartFrame(void)
8628 {
8629         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8630
8631         switch(vid.renderpath)
8632         {
8633         case RENDERPATH_GL20:
8634         case RENDERPATH_CGGL:
8635         case RENDERPATH_D3D9:
8636         case RENDERPATH_D3D10:
8637         case RENDERPATH_D3D11:
8638                 break;
8639         case RENDERPATH_GL13:
8640         case RENDERPATH_GL11:
8641                 return;
8642         }
8643
8644         // set bloomwidth and bloomheight to the bloom resolution that will be
8645         // used (often less than the screen resolution for faster rendering)
8646         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8647         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8648         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8649         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8650         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8651
8652         // calculate desired texture sizes
8653         if (vid.support.arb_texture_non_power_of_two)
8654         {
8655                 screentexturewidth = r_refdef.view.width;
8656                 screentextureheight = r_refdef.view.height;
8657                 bloomtexturewidth = r_bloomstate.bloomwidth;
8658                 bloomtextureheight = r_bloomstate.bloomheight;
8659         }
8660         else
8661         {
8662                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8663                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8664                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8665                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8666         }
8667
8668         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))
8669         {
8670                 Cvar_SetValueQuick(&r_hdr, 0);
8671                 Cvar_SetValueQuick(&r_bloom, 0);
8672                 Cvar_SetValueQuick(&r_motionblur, 0);
8673                 Cvar_SetValueQuick(&r_damageblur, 0);
8674         }
8675
8676         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)))
8677                 screentexturewidth = screentextureheight = 0;
8678         if (!r_hdr.integer && !r_bloom.integer)
8679                 bloomtexturewidth = bloomtextureheight = 0;
8680
8681         // allocate textures as needed
8682         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8683         {
8684                 if (r_bloomstate.texture_screen)
8685                         R_FreeTexture(r_bloomstate.texture_screen);
8686                 r_bloomstate.texture_screen = NULL;
8687                 r_bloomstate.screentexturewidth = screentexturewidth;
8688                 r_bloomstate.screentextureheight = screentextureheight;
8689                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8690                         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);
8691         }
8692         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8693         {
8694                 if (r_bloomstate.texture_bloom)
8695                         R_FreeTexture(r_bloomstate.texture_bloom);
8696                 r_bloomstate.texture_bloom = NULL;
8697                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8698                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8699                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8700                         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);
8701         }
8702
8703         // when doing a reduced render (HDR) we want to use a smaller area
8704         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8705         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8706         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8707         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8708         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8709
8710         // set up a texcoord array for the full resolution screen image
8711         // (we have to keep this around to copy back during final render)
8712         r_bloomstate.screentexcoord2f[0] = 0;
8713         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8714         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8715         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8716         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8717         r_bloomstate.screentexcoord2f[5] = 0;
8718         r_bloomstate.screentexcoord2f[6] = 0;
8719         r_bloomstate.screentexcoord2f[7] = 0;
8720
8721         // set up a texcoord array for the reduced resolution bloom image
8722         // (which will be additive blended over the screen image)
8723         r_bloomstate.bloomtexcoord2f[0] = 0;
8724         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8725         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8726         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8727         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8728         r_bloomstate.bloomtexcoord2f[5] = 0;
8729         r_bloomstate.bloomtexcoord2f[6] = 0;
8730         r_bloomstate.bloomtexcoord2f[7] = 0;
8731
8732         switch(vid.renderpath)
8733         {
8734         case RENDERPATH_GL11:
8735         case RENDERPATH_GL13:
8736         case RENDERPATH_GL20:
8737         case RENDERPATH_CGGL:
8738                 break;
8739         case RENDERPATH_D3D9:
8740         case RENDERPATH_D3D10:
8741         case RENDERPATH_D3D11:
8742                 {
8743                         int i;
8744                         for (i = 0;i < 4;i++)
8745                         {
8746                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8747                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8748                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8749                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8750                         }
8751                 }
8752                 break;
8753         }
8754
8755         if (r_hdr.integer || r_bloom.integer)
8756         {
8757                 r_bloomstate.enabled = true;
8758                 r_bloomstate.hdr = r_hdr.integer != 0;
8759         }
8760
8761         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);
8762 }
8763
8764 void R_Bloom_CopyBloomTexture(float colorscale)
8765 {
8766         r_refdef.stats.bloom++;
8767
8768         // scale down screen texture to the bloom texture size
8769         CHECKGLERROR
8770         R_SetViewport(&r_bloomstate.viewport);
8771         GL_BlendFunc(GL_ONE, GL_ZERO);
8772         GL_Color(colorscale, colorscale, colorscale, 1);
8773         // 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...
8774         switch(vid.renderpath)
8775         {
8776         case RENDERPATH_GL11:
8777         case RENDERPATH_GL13:
8778         case RENDERPATH_GL20:
8779         case RENDERPATH_CGGL:
8780                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8781                 break;
8782         case RENDERPATH_D3D9:
8783         case RENDERPATH_D3D10:
8784         case RENDERPATH_D3D11:
8785                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8786                 break;
8787         }
8788         // TODO: do boxfilter scale-down in shader?
8789         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8790         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8791         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8792
8793         // we now have a bloom image in the framebuffer
8794         // copy it into the bloom image texture for later processing
8795         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);
8796         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8797 }
8798
8799 void R_Bloom_CopyHDRTexture(void)
8800 {
8801         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);
8802         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8803 }
8804
8805 void R_Bloom_MakeTexture(void)
8806 {
8807         int x, range, dir;
8808         float xoffset, yoffset, r, brighten;
8809
8810         r_refdef.stats.bloom++;
8811
8812         R_ResetViewRendering2D();
8813
8814         // we have a bloom image in the framebuffer
8815         CHECKGLERROR
8816         R_SetViewport(&r_bloomstate.viewport);
8817
8818         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8819         {
8820                 x *= 2;
8821                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8822                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8823                 GL_Color(r,r,r,1);
8824                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8825                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8826                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8827                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8828
8829                 // copy the vertically blurred bloom view to a texture
8830                 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);
8831                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8832         }
8833
8834         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8835         brighten = r_bloom_brighten.value;
8836         if (r_hdr.integer)
8837                 brighten *= r_hdr_range.value;
8838         brighten = sqrt(brighten);
8839         if(range >= 1)
8840                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8841         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8842
8843         for (dir = 0;dir < 2;dir++)
8844         {
8845                 // blend on at multiple vertical offsets to achieve a vertical blur
8846                 // TODO: do offset blends using GLSL
8847                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8848                 GL_BlendFunc(GL_ONE, GL_ZERO);
8849                 for (x = -range;x <= range;x++)
8850                 {
8851                         if (!dir){xoffset = 0;yoffset = x;}
8852                         else {xoffset = x;yoffset = 0;}
8853                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8854                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8855                         // compute a texcoord array with the specified x and y offset
8856                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8857                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8858                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8859                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8860                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8861                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8862                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8863                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8864                         // this r value looks like a 'dot' particle, fading sharply to
8865                         // black at the edges
8866                         // (probably not realistic but looks good enough)
8867                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8868                         //r = brighten/(range*2+1);
8869                         r = brighten / (range * 2 + 1);
8870                         if(range >= 1)
8871                                 r *= (1 - x*x/(float)(range*range));
8872                         GL_Color(r, r, r, 1);
8873                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8874                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8875                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8876                         GL_BlendFunc(GL_ONE, GL_ONE);
8877                 }
8878
8879                 // copy the vertically blurred bloom view to a texture
8880                 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);
8881                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8882         }
8883 }
8884
8885 void R_HDR_RenderBloomTexture(void)
8886 {
8887         int oldwidth, oldheight;
8888         float oldcolorscale;
8889
8890         oldcolorscale = r_refdef.view.colorscale;
8891         oldwidth = r_refdef.view.width;
8892         oldheight = r_refdef.view.height;
8893         r_refdef.view.width = r_bloomstate.bloomwidth;
8894         r_refdef.view.height = r_bloomstate.bloomheight;
8895
8896         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8897         // TODO: add exposure compensation features
8898         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8899
8900         r_refdef.view.showdebug = false;
8901         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8902
8903         R_ResetViewRendering3D();
8904
8905         R_ClearScreen(r_refdef.fogenabled);
8906         if (r_timereport_active)
8907                 R_TimeReport("HDRclear");
8908
8909         R_View_Update();
8910         if (r_timereport_active)
8911                 R_TimeReport("visibility");
8912
8913         // only do secondary renders with HDR if r_hdr is 2 or higher
8914         r_waterstate.numwaterplanes = 0;
8915         if (r_waterstate.enabled && r_hdr.integer >= 2)
8916                 R_RenderWaterPlanes();
8917
8918         r_refdef.view.showdebug = true;
8919         R_RenderScene();
8920         r_waterstate.numwaterplanes = 0;
8921
8922         R_ResetViewRendering2D();
8923
8924         R_Bloom_CopyHDRTexture();
8925         R_Bloom_MakeTexture();
8926
8927         // restore the view settings
8928         r_refdef.view.width = oldwidth;
8929         r_refdef.view.height = oldheight;
8930         r_refdef.view.colorscale = oldcolorscale;
8931
8932         R_ResetViewRendering3D();
8933
8934         R_ClearScreen(r_refdef.fogenabled);
8935         if (r_timereport_active)
8936                 R_TimeReport("viewclear");
8937 }
8938
8939 static void R_BlendView(void)
8940 {
8941         unsigned int permutation;
8942         float uservecs[4][4];
8943
8944         switch (vid.renderpath)
8945         {
8946         case RENDERPATH_GL20:
8947         case RENDERPATH_CGGL:
8948         case RENDERPATH_D3D9:
8949         case RENDERPATH_D3D10:
8950         case RENDERPATH_D3D11:
8951                 permutation =
8952                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8953                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8954                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8955                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8956                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8957
8958                 if (r_bloomstate.texture_screen)
8959                 {
8960                         // make sure the buffer is available
8961                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8962
8963                         R_ResetViewRendering2D();
8964
8965                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8966                         {
8967                                 // declare variables
8968                                 float speed;
8969                                 static float avgspeed;
8970
8971                                 speed = VectorLength(cl.movement_velocity);
8972
8973                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8974                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8975
8976                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8977                                 speed = bound(0, speed, 1);
8978                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8979
8980                                 // calculate values into a standard alpha
8981                                 cl.motionbluralpha = 1 - exp(-
8982                                                 (
8983                                                  (r_motionblur.value * speed / 80)
8984                                                  +
8985                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8986                                                 )
8987                                                 /
8988                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8989                                            );
8990
8991                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8992                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8993                                 // apply the blur
8994                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8995                                 {
8996                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8997                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8998                                         switch(vid.renderpath)
8999                                         {
9000                                         case RENDERPATH_GL11:
9001                                         case RENDERPATH_GL13:
9002                                         case RENDERPATH_GL20:
9003                                         case RENDERPATH_CGGL:
9004                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9005                                                 break;
9006                                         case RENDERPATH_D3D9:
9007                                         case RENDERPATH_D3D10:
9008                                         case RENDERPATH_D3D11:
9009                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9010                                                 break;
9011                                         }
9012                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9013                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9014                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9015                                 }
9016                         }
9017
9018                         // copy view into the screen texture
9019                         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);
9020                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9021                 }
9022                 else if (!r_bloomstate.texture_bloom)
9023                 {
9024                         // we may still have to do view tint...
9025                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9026                         {
9027                                 // apply a color tint to the whole view
9028                                 R_ResetViewRendering2D();
9029                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9030                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9031                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9032                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9033                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9034                         }
9035                         break; // no screen processing, no bloom, skip it
9036                 }
9037
9038                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9039                 {
9040                         // render simple bloom effect
9041                         // copy the screen and shrink it and darken it for the bloom process
9042                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9043                         // make the bloom texture
9044                         R_Bloom_MakeTexture();
9045                 }
9046
9047 #if _MSC_VER >= 1400
9048 #define sscanf sscanf_s
9049 #endif
9050                 memset(uservecs, 0, sizeof(uservecs));
9051                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9052                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9053                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9054                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9055
9056                 R_ResetViewRendering2D();
9057                 GL_Color(1, 1, 1, 1);
9058                 GL_BlendFunc(GL_ONE, GL_ZERO);
9059
9060                 switch(vid.renderpath)
9061                 {
9062                 case RENDERPATH_GL20:
9063                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9064                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9065                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9066                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9067                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9068                         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]);
9069                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9070                         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]);
9071                         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]);
9072                         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]);
9073                         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]);
9074                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9075                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9076                         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);
9077                         break;
9078                 case RENDERPATH_CGGL:
9079 #ifdef SUPPORTCG
9080                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9081                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9082                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9083                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9084                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9085                         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
9086                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9087                         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
9088                         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
9089                         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
9090                         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
9091                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9092                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9093                         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);
9094 #endif
9095                         break;
9096                 case RENDERPATH_D3D9:
9097 #ifdef SUPPORTD3D
9098                         // 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...
9099                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9100                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9101                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9102                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9103                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9104                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9105                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9106                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9107                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9108                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9109                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9110                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9111                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9112                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9113 #endif
9114                         break;
9115                 case RENDERPATH_D3D10:
9116                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9117                         break;
9118                 case RENDERPATH_D3D11:
9119                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9120                         break;
9121                 default:
9122                         break;
9123                 }
9124                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9125                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9126                 break;
9127         case RENDERPATH_GL13:
9128         case RENDERPATH_GL11:
9129                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9130                 {
9131                         // apply a color tint to the whole view
9132                         R_ResetViewRendering2D();
9133                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9134                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9135                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9136                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9137                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9138                 }
9139                 break;
9140         }
9141 }
9142
9143 matrix4x4_t r_waterscrollmatrix;
9144
9145 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9146 {
9147         if (r_refdef.fog_density)
9148         {
9149                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9150                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9151                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9152
9153                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9154                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9155                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9156                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9157
9158                 {
9159                         vec3_t fogvec;
9160                         VectorCopy(r_refdef.fogcolor, fogvec);
9161                         //   color.rgb *= ContrastBoost * SceneBrightness;
9162                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9163                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9164                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9165                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9166                 }
9167         }
9168 }
9169
9170 void R_UpdateVariables(void)
9171 {
9172         R_Textures_Frame();
9173
9174         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9175
9176         r_refdef.farclip = r_farclip_base.value;
9177         if (r_refdef.scene.worldmodel)
9178                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9179         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9180
9181         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9182                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9183         r_refdef.polygonfactor = 0;
9184         r_refdef.polygonoffset = 0;
9185         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9186         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9187
9188         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9189         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9190         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9191         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9192         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9193         if (r_showsurfaces.integer)
9194         {
9195                 r_refdef.scene.rtworld = false;
9196                 r_refdef.scene.rtworldshadows = false;
9197                 r_refdef.scene.rtdlight = false;
9198                 r_refdef.scene.rtdlightshadows = false;
9199                 r_refdef.lightmapintensity = 0;
9200         }
9201
9202         if (gamemode == GAME_NEHAHRA)
9203         {
9204                 if (gl_fogenable.integer)
9205                 {
9206                         r_refdef.oldgl_fogenable = true;
9207                         r_refdef.fog_density = gl_fogdensity.value;
9208                         r_refdef.fog_red = gl_fogred.value;
9209                         r_refdef.fog_green = gl_foggreen.value;
9210                         r_refdef.fog_blue = gl_fogblue.value;
9211                         r_refdef.fog_alpha = 1;
9212                         r_refdef.fog_start = 0;
9213                         r_refdef.fog_end = gl_skyclip.value;
9214                         r_refdef.fog_height = 1<<30;
9215                         r_refdef.fog_fadedepth = 128;
9216                 }
9217                 else if (r_refdef.oldgl_fogenable)
9218                 {
9219                         r_refdef.oldgl_fogenable = false;
9220                         r_refdef.fog_density = 0;
9221                         r_refdef.fog_red = 0;
9222                         r_refdef.fog_green = 0;
9223                         r_refdef.fog_blue = 0;
9224                         r_refdef.fog_alpha = 0;
9225                         r_refdef.fog_start = 0;
9226                         r_refdef.fog_end = 0;
9227                         r_refdef.fog_height = 1<<30;
9228                         r_refdef.fog_fadedepth = 128;
9229                 }
9230         }
9231
9232         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9233         r_refdef.fog_start = max(0, r_refdef.fog_start);
9234         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9235
9236         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9237
9238         if (r_refdef.fog_density && r_drawfog.integer)
9239         {
9240                 r_refdef.fogenabled = true;
9241                 // this is the point where the fog reaches 0.9986 alpha, which we
9242                 // consider a good enough cutoff point for the texture
9243                 // (0.9986 * 256 == 255.6)
9244                 if (r_fog_exp2.integer)
9245                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9246                 else
9247                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9248                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9249                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9250                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9251                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9252                         R_BuildFogHeightTexture();
9253                 // fog color was already set
9254                 // update the fog texture
9255                 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)
9256                         R_BuildFogTexture();
9257                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9258                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9259         }
9260         else
9261                 r_refdef.fogenabled = false;
9262
9263         switch(vid.renderpath)
9264         {
9265         case RENDERPATH_GL20:
9266         case RENDERPATH_CGGL:
9267         case RENDERPATH_D3D9:
9268         case RENDERPATH_D3D10:
9269         case RENDERPATH_D3D11:
9270                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9271                 {
9272                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9273                         {
9274                                 // build GLSL gamma texture
9275 #define RAMPWIDTH 256
9276                                 unsigned short ramp[RAMPWIDTH * 3];
9277                                 unsigned char rampbgr[RAMPWIDTH][4];
9278                                 int i;
9279
9280                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9281
9282                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9283                                 for(i = 0; i < RAMPWIDTH; ++i)
9284                                 {
9285                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9286                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9287                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9288                                         rampbgr[i][3] = 0;
9289                                 }
9290                                 if (r_texture_gammaramps)
9291                                 {
9292                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9293                                 }
9294                                 else
9295                                 {
9296                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9297                                 }
9298                         }
9299                 }
9300                 else
9301                 {
9302                         // remove GLSL gamma texture
9303                 }
9304                 break;
9305         case RENDERPATH_GL13:
9306         case RENDERPATH_GL11:
9307                 break;
9308         }
9309 }
9310
9311 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9312 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9313 /*
9314 ================
9315 R_SelectScene
9316 ================
9317 */
9318 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9319         if( scenetype != r_currentscenetype ) {
9320                 // store the old scenetype
9321                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9322                 r_currentscenetype = scenetype;
9323                 // move in the new scene
9324                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9325         }
9326 }
9327
9328 /*
9329 ================
9330 R_GetScenePointer
9331 ================
9332 */
9333 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9334 {
9335         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9336         if( scenetype == r_currentscenetype ) {
9337                 return &r_refdef.scene;
9338         } else {
9339                 return &r_scenes_store[ scenetype ];
9340         }
9341 }
9342
9343 /*
9344 ================
9345 R_RenderView
9346 ================
9347 */
9348 void R_RenderView(void)
9349 {
9350         if (r_timereport_active)
9351                 R_TimeReport("start");
9352         r_textureframe++; // used only by R_GetCurrentTexture
9353         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9354
9355         if (!r_drawentities.integer)
9356                 r_refdef.scene.numentities = 0;
9357
9358         R_AnimCache_ClearCache();
9359         R_FrameData_NewFrame();
9360
9361         if (r_refdef.view.isoverlay)
9362         {
9363                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9364                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9365                 R_TimeReport("depthclear");
9366
9367                 r_refdef.view.showdebug = false;
9368
9369                 r_waterstate.enabled = false;
9370                 r_waterstate.numwaterplanes = 0;
9371
9372                 R_RenderScene();
9373
9374                 CHECKGLERROR
9375                 return;
9376         }
9377
9378         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9379                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9380
9381         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9382
9383         R_RenderView_UpdateViewVectors();
9384
9385         R_Shadow_UpdateWorldLightSelection();
9386
9387         R_Bloom_StartFrame();
9388         R_Water_StartFrame();
9389
9390         CHECKGLERROR
9391         if (r_timereport_active)
9392                 R_TimeReport("viewsetup");
9393
9394         R_ResetViewRendering3D();
9395
9396         if (r_refdef.view.clear || r_refdef.fogenabled)
9397         {
9398                 R_ClearScreen(r_refdef.fogenabled);
9399                 if (r_timereport_active)
9400                         R_TimeReport("viewclear");
9401         }
9402         r_refdef.view.clear = true;
9403
9404         // this produces a bloom texture to be used in R_BlendView() later
9405         if (r_hdr.integer && r_bloomstate.bloomwidth)
9406         {
9407                 R_HDR_RenderBloomTexture();
9408                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9409                 r_textureframe++; // used only by R_GetCurrentTexture
9410         }
9411
9412         r_refdef.view.showdebug = true;
9413
9414         R_View_Update();
9415         if (r_timereport_active)
9416                 R_TimeReport("visibility");
9417
9418         r_waterstate.numwaterplanes = 0;
9419         if (r_waterstate.enabled)
9420                 R_RenderWaterPlanes();
9421
9422         R_RenderScene();
9423         r_waterstate.numwaterplanes = 0;
9424
9425         R_BlendView();
9426         if (r_timereport_active)
9427                 R_TimeReport("blendview");
9428
9429         GL_Scissor(0, 0, vid.width, vid.height);
9430         GL_ScissorTest(false);
9431         CHECKGLERROR
9432 }
9433
9434 void R_RenderWaterPlanes(void)
9435 {
9436         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9437         {
9438                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9439                 if (r_timereport_active)
9440                         R_TimeReport("waterworld");
9441         }
9442
9443         // don't let sound skip if going slow
9444         if (r_refdef.scene.extraupdate)
9445                 S_ExtraUpdate ();
9446
9447         R_DrawModelsAddWaterPlanes();
9448         if (r_timereport_active)
9449                 R_TimeReport("watermodels");
9450
9451         if (r_waterstate.numwaterplanes)
9452         {
9453                 R_Water_ProcessPlanes();
9454                 if (r_timereport_active)
9455                         R_TimeReport("waterscenes");
9456         }
9457 }
9458
9459 extern void R_DrawLightningBeams (void);
9460 extern void VM_CL_AddPolygonsToMeshQueue (void);
9461 extern void R_DrawPortals (void);
9462 extern cvar_t cl_locs_show;
9463 static void R_DrawLocs(void);
9464 static void R_DrawEntityBBoxes(void);
9465 static void R_DrawModelDecals(void);
9466 extern void R_DrawModelShadows(void);
9467 extern void R_DrawModelShadowMaps(void);
9468 extern cvar_t cl_decals_newsystem;
9469 extern qboolean r_shadow_usingdeferredprepass;
9470 void R_RenderScene(void)
9471 {
9472         qboolean shadowmapping = false;
9473
9474         if (r_timereport_active)
9475                 R_TimeReport("beginscene");
9476
9477         r_refdef.stats.renders++;
9478
9479         R_UpdateFogColor();
9480
9481         // don't let sound skip if going slow
9482         if (r_refdef.scene.extraupdate)
9483                 S_ExtraUpdate ();
9484
9485         R_MeshQueue_BeginScene();
9486
9487         R_SkyStartFrame();
9488
9489         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);
9490
9491         if (r_timereport_active)
9492                 R_TimeReport("skystartframe");
9493
9494         if (cl.csqc_vidvars.drawworld)
9495         {
9496                 // don't let sound skip if going slow
9497                 if (r_refdef.scene.extraupdate)
9498                         S_ExtraUpdate ();
9499
9500                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9501                 {
9502                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9503                         if (r_timereport_active)
9504                                 R_TimeReport("worldsky");
9505                 }
9506
9507                 if (R_DrawBrushModelsSky() && r_timereport_active)
9508                         R_TimeReport("bmodelsky");
9509
9510                 if (skyrendermasked && skyrenderlater)
9511                 {
9512                         // we have to force off the water clipping plane while rendering sky
9513                         R_SetupView(false);
9514                         R_Sky();
9515                         R_SetupView(true);
9516                         if (r_timereport_active)
9517                                 R_TimeReport("sky");
9518                 }
9519         }
9520
9521         R_AnimCache_CacheVisibleEntities();
9522         if (r_timereport_active)
9523                 R_TimeReport("animation");
9524
9525         R_Shadow_PrepareLights();
9526         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9527                 R_Shadow_PrepareModelShadows();
9528         if (r_timereport_active)
9529                 R_TimeReport("preparelights");
9530
9531         if (R_Shadow_ShadowMappingEnabled())
9532                 shadowmapping = true;
9533
9534         if (r_shadow_usingdeferredprepass)
9535                 R_Shadow_DrawPrepass();
9536
9537         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9538         {
9539                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9540                 if (r_timereport_active)
9541                         R_TimeReport("worlddepth");
9542         }
9543         if (r_depthfirst.integer >= 2)
9544         {
9545                 R_DrawModelsDepth();
9546                 if (r_timereport_active)
9547                         R_TimeReport("modeldepth");
9548         }
9549
9550         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9551         {
9552                 R_DrawModelShadowMaps();
9553                 R_ResetViewRendering3D();
9554                 // don't let sound skip if going slow
9555                 if (r_refdef.scene.extraupdate)
9556                         S_ExtraUpdate ();
9557         }
9558
9559         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9560         {
9561                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9562                 if (r_timereport_active)
9563                         R_TimeReport("world");
9564         }
9565
9566         // don't let sound skip if going slow
9567         if (r_refdef.scene.extraupdate)
9568                 S_ExtraUpdate ();
9569
9570         R_DrawModels();
9571         if (r_timereport_active)
9572                 R_TimeReport("models");
9573
9574         // don't let sound skip if going slow
9575         if (r_refdef.scene.extraupdate)
9576                 S_ExtraUpdate ();
9577
9578         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9579         {
9580                 R_DrawModelShadows();
9581                 R_ResetViewRendering3D();
9582                 // don't let sound skip if going slow
9583                 if (r_refdef.scene.extraupdate)
9584                         S_ExtraUpdate ();
9585         }
9586
9587         if (!r_shadow_usingdeferredprepass)
9588         {
9589                 R_Shadow_DrawLights();
9590                 if (r_timereport_active)
9591                         R_TimeReport("rtlights");
9592         }
9593
9594         // don't let sound skip if going slow
9595         if (r_refdef.scene.extraupdate)
9596                 S_ExtraUpdate ();
9597
9598         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9599         {
9600                 R_DrawModelShadows();
9601                 R_ResetViewRendering3D();
9602                 // don't let sound skip if going slow
9603                 if (r_refdef.scene.extraupdate)
9604                         S_ExtraUpdate ();
9605         }
9606
9607         if (cl.csqc_vidvars.drawworld)
9608         {
9609                 if (cl_decals_newsystem.integer)
9610                 {
9611                         R_DrawModelDecals();
9612                         if (r_timereport_active)
9613                                 R_TimeReport("modeldecals");
9614                 }
9615                 else
9616                 {
9617                         R_DrawDecals();
9618                         if (r_timereport_active)
9619                                 R_TimeReport("decals");
9620                 }
9621
9622                 R_DrawParticles();
9623                 if (r_timereport_active)
9624                         R_TimeReport("particles");
9625
9626                 R_DrawExplosions();
9627                 if (r_timereport_active)
9628                         R_TimeReport("explosions");
9629
9630                 R_DrawLightningBeams();
9631                 if (r_timereport_active)
9632                         R_TimeReport("lightning");
9633         }
9634
9635         VM_CL_AddPolygonsToMeshQueue();
9636
9637         if (r_refdef.view.showdebug)
9638         {
9639                 if (cl_locs_show.integer)
9640                 {
9641                         R_DrawLocs();
9642                         if (r_timereport_active)
9643                                 R_TimeReport("showlocs");
9644                 }
9645
9646                 if (r_drawportals.integer)
9647                 {
9648                         R_DrawPortals();
9649                         if (r_timereport_active)
9650                                 R_TimeReport("portals");
9651                 }
9652
9653                 if (r_showbboxes.value > 0)
9654                 {
9655                         R_DrawEntityBBoxes();
9656                         if (r_timereport_active)
9657                                 R_TimeReport("bboxes");
9658                 }
9659         }
9660
9661         R_MeshQueue_RenderTransparent();
9662         if (r_timereport_active)
9663                 R_TimeReport("drawtrans");
9664
9665         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))
9666         {
9667                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9668                 if (r_timereport_active)
9669                         R_TimeReport("worlddebug");
9670                 R_DrawModelsDebug();
9671                 if (r_timereport_active)
9672                         R_TimeReport("modeldebug");
9673         }
9674
9675         if (cl.csqc_vidvars.drawworld)
9676         {
9677                 R_Shadow_DrawCoronas();
9678                 if (r_timereport_active)
9679                         R_TimeReport("coronas");
9680         }
9681
9682         // don't let sound skip if going slow
9683         if (r_refdef.scene.extraupdate)
9684                 S_ExtraUpdate ();
9685
9686         R_ResetViewRendering2D();
9687 }
9688
9689 static const unsigned short bboxelements[36] =
9690 {
9691         5, 1, 3, 5, 3, 7,
9692         6, 2, 0, 6, 0, 4,
9693         7, 3, 2, 7, 2, 6,
9694         4, 0, 1, 4, 1, 5,
9695         4, 5, 7, 4, 7, 6,
9696         1, 0, 2, 1, 2, 3,
9697 };
9698
9699 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9700 {
9701         int i;
9702         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9703
9704         RSurf_ActiveWorldEntity();
9705
9706         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9707         GL_DepthMask(false);
9708         GL_DepthRange(0, 1);
9709         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9710         R_Mesh_ResetTextureState();
9711
9712         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9713         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9714         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9715         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9716         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9717         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9718         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9719         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9720         R_FillColors(color4f, 8, cr, cg, cb, ca);
9721         if (r_refdef.fogenabled)
9722         {
9723                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9724                 {
9725                         f1 = RSurf_FogVertex(v);
9726                         f2 = 1 - f1;
9727                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9728                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9729                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9730                 }
9731         }
9732         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9733         R_Mesh_ResetTextureState();
9734         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9735         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9736 }
9737
9738 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9739 {
9740         int i;
9741         float color[4];
9742         prvm_edict_t *edict;
9743         prvm_prog_t *prog_save = prog;
9744
9745         // this function draws bounding boxes of server entities
9746         if (!sv.active)
9747                 return;
9748
9749         GL_CullFace(GL_NONE);
9750         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9751
9752         prog = 0;
9753         SV_VM_Begin();
9754         for (i = 0;i < numsurfaces;i++)
9755         {
9756                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9757                 switch ((int)edict->fields.server->solid)
9758                 {
9759                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9760                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9761                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9762                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9763                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9764                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9765                 }
9766                 color[3] *= r_showbboxes.value;
9767                 color[3] = bound(0, color[3], 1);
9768                 GL_DepthTest(!r_showdisabledepthtest.integer);
9769                 GL_CullFace(r_refdef.view.cullface_front);
9770                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9771         }
9772         SV_VM_End();
9773         prog = prog_save;
9774 }
9775
9776 static void R_DrawEntityBBoxes(void)
9777 {
9778         int i;
9779         prvm_edict_t *edict;
9780         vec3_t center;
9781         prvm_prog_t *prog_save = prog;
9782
9783         // this function draws bounding boxes of server entities
9784         if (!sv.active)
9785                 return;
9786
9787         prog = 0;
9788         SV_VM_Begin();
9789         for (i = 0;i < prog->num_edicts;i++)
9790         {
9791                 edict = PRVM_EDICT_NUM(i);
9792                 if (edict->priv.server->free)
9793                         continue;
9794                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9795                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9796                         continue;
9797                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9798                         continue;
9799                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9800                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9801         }
9802         SV_VM_End();
9803         prog = prog_save;
9804 }
9805
9806 static const int nomodelelement3i[24] =
9807 {
9808         5, 2, 0,
9809         5, 1, 2,
9810         5, 0, 3,
9811         5, 3, 1,
9812         0, 2, 4,
9813         2, 1, 4,
9814         3, 0, 4,
9815         1, 3, 4
9816 };
9817
9818 static const unsigned short nomodelelement3s[24] =
9819 {
9820         5, 2, 0,
9821         5, 1, 2,
9822         5, 0, 3,
9823         5, 3, 1,
9824         0, 2, 4,
9825         2, 1, 4,
9826         3, 0, 4,
9827         1, 3, 4
9828 };
9829
9830 static const float nomodelvertex3f[6*3] =
9831 {
9832         -16,   0,   0,
9833          16,   0,   0,
9834           0, -16,   0,
9835           0,  16,   0,
9836           0,   0, -16,
9837           0,   0,  16
9838 };
9839
9840 static const float nomodelcolor4f[6*4] =
9841 {
9842         0.0f, 0.0f, 0.5f, 1.0f,
9843         0.0f, 0.0f, 0.5f, 1.0f,
9844         0.0f, 0.5f, 0.0f, 1.0f,
9845         0.0f, 0.5f, 0.0f, 1.0f,
9846         0.5f, 0.0f, 0.0f, 1.0f,
9847         0.5f, 0.0f, 0.0f, 1.0f
9848 };
9849
9850 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9851 {
9852         int i;
9853         float f1, f2, *c;
9854         float color4f[6*4];
9855
9856         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);
9857
9858         // this is only called once per entity so numsurfaces is always 1, and
9859         // surfacelist is always {0}, so this code does not handle batches
9860
9861         if (rsurface.ent_flags & RENDER_ADDITIVE)
9862         {
9863                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9864                 GL_DepthMask(false);
9865         }
9866         else if (rsurface.colormod[3] < 1)
9867         {
9868                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9869                 GL_DepthMask(false);
9870         }
9871         else
9872         {
9873                 GL_BlendFunc(GL_ONE, GL_ZERO);
9874                 GL_DepthMask(true);
9875         }
9876         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9877         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9878         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9879         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9880         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9881         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9882         for (i = 0, c = color4f;i < 6;i++, c += 4)
9883         {
9884                 c[0] *= rsurface.colormod[0];
9885                 c[1] *= rsurface.colormod[1];
9886                 c[2] *= rsurface.colormod[2];
9887                 c[3] *= rsurface.colormod[3];
9888         }
9889         if (r_refdef.fogenabled)
9890         {
9891                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9892                 {
9893                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9894                         f2 = 1 - f1;
9895                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9896                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9897                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9898                 }
9899         }
9900         R_Mesh_ResetTextureState();
9901         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9902         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9903 }
9904
9905 void R_DrawNoModel(entity_render_t *ent)
9906 {
9907         vec3_t org;
9908         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9909         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9910                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9911         else
9912                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9913 }
9914
9915 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9916 {
9917         vec3_t right1, right2, diff, normal;
9918
9919         VectorSubtract (org2, org1, normal);
9920
9921         // calculate 'right' vector for start
9922         VectorSubtract (r_refdef.view.origin, org1, diff);
9923         CrossProduct (normal, diff, right1);
9924         VectorNormalize (right1);
9925
9926         // calculate 'right' vector for end
9927         VectorSubtract (r_refdef.view.origin, org2, diff);
9928         CrossProduct (normal, diff, right2);
9929         VectorNormalize (right2);
9930
9931         vert[ 0] = org1[0] + width * right1[0];
9932         vert[ 1] = org1[1] + width * right1[1];
9933         vert[ 2] = org1[2] + width * right1[2];
9934         vert[ 3] = org1[0] - width * right1[0];
9935         vert[ 4] = org1[1] - width * right1[1];
9936         vert[ 5] = org1[2] - width * right1[2];
9937         vert[ 6] = org2[0] - width * right2[0];
9938         vert[ 7] = org2[1] - width * right2[1];
9939         vert[ 8] = org2[2] - width * right2[2];
9940         vert[ 9] = org2[0] + width * right2[0];
9941         vert[10] = org2[1] + width * right2[1];
9942         vert[11] = org2[2] + width * right2[2];
9943 }
9944
9945 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)
9946 {
9947         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9948         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9949         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9950         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9951         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9952         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9953         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9954         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9955         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9956         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9957         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9958         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9959 }
9960
9961 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9962 {
9963         int i;
9964         float *vertex3f;
9965         float v[3];
9966         VectorSet(v, x, y, z);
9967         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9968                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9969                         break;
9970         if (i == mesh->numvertices)
9971         {
9972                 if (mesh->numvertices < mesh->maxvertices)
9973                 {
9974                         VectorCopy(v, vertex3f);
9975                         mesh->numvertices++;
9976                 }
9977                 return mesh->numvertices;
9978         }
9979         else
9980                 return i;
9981 }
9982
9983 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9984 {
9985         int i;
9986         int *e, element[3];
9987         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9988         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9989         e = mesh->element3i + mesh->numtriangles * 3;
9990         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9991         {
9992                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9993                 if (mesh->numtriangles < mesh->maxtriangles)
9994                 {
9995                         *e++ = element[0];
9996                         *e++ = element[1];
9997                         *e++ = element[2];
9998                         mesh->numtriangles++;
9999                 }
10000                 element[1] = element[2];
10001         }
10002 }
10003
10004 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10005 {
10006         int i;
10007         int *e, element[3];
10008         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10009         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10010         e = mesh->element3i + mesh->numtriangles * 3;
10011         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10012         {
10013                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10014                 if (mesh->numtriangles < mesh->maxtriangles)
10015                 {
10016                         *e++ = element[0];
10017                         *e++ = element[1];
10018                         *e++ = element[2];
10019                         mesh->numtriangles++;
10020                 }
10021                 element[1] = element[2];
10022         }
10023 }
10024
10025 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10026 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10027 {
10028         int planenum, planenum2;
10029         int w;
10030         int tempnumpoints;
10031         mplane_t *plane, *plane2;
10032         double maxdist;
10033         double temppoints[2][256*3];
10034         // figure out how large a bounding box we need to properly compute this brush
10035         maxdist = 0;
10036         for (w = 0;w < numplanes;w++)
10037                 maxdist = max(maxdist, fabs(planes[w].dist));
10038         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10039         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10040         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10041         {
10042                 w = 0;
10043                 tempnumpoints = 4;
10044                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10045                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10046                 {
10047                         if (planenum2 == planenum)
10048                                 continue;
10049                         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);
10050                         w = !w;
10051                 }
10052                 if (tempnumpoints < 3)
10053                         continue;
10054                 // generate elements forming a triangle fan for this polygon
10055                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10056         }
10057 }
10058
10059 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)
10060 {
10061         texturelayer_t *layer;
10062         layer = t->currentlayers + t->currentnumlayers++;
10063         layer->type = type;
10064         layer->depthmask = depthmask;
10065         layer->blendfunc1 = blendfunc1;
10066         layer->blendfunc2 = blendfunc2;
10067         layer->texture = texture;
10068         layer->texmatrix = *matrix;
10069         layer->color[0] = r;
10070         layer->color[1] = g;
10071         layer->color[2] = b;
10072         layer->color[3] = a;
10073 }
10074
10075 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10076 {
10077         if(parms[0] == 0 && parms[1] == 0)
10078                 return false;
10079         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10080                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10081                         return false;
10082         return true;
10083 }
10084
10085 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10086 {
10087         double index, f;
10088         index = parms[2] + r_refdef.scene.time * parms[3];
10089         index -= floor(index);
10090         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10091         {
10092         default:
10093         case Q3WAVEFUNC_NONE:
10094         case Q3WAVEFUNC_NOISE:
10095         case Q3WAVEFUNC_COUNT:
10096                 f = 0;
10097                 break;
10098         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10099         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10100         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10101         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10102         case Q3WAVEFUNC_TRIANGLE:
10103                 index *= 4;
10104                 f = index - floor(index);
10105                 if (index < 1)
10106                         f = f;
10107                 else if (index < 2)
10108                         f = 1 - f;
10109                 else if (index < 3)
10110                         f = -f;
10111                 else
10112                         f = -(1 - f);
10113                 break;
10114         }
10115         f = parms[0] + parms[1] * f;
10116         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10117                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10118         return (float) f;
10119 }
10120
10121 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10122 {
10123         int w, h, idx;
10124         float f;
10125         float tcmat[12];
10126         matrix4x4_t matrix, temp;
10127         switch(tcmod->tcmod)
10128         {
10129                 case Q3TCMOD_COUNT:
10130                 case Q3TCMOD_NONE:
10131                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10132                                 matrix = r_waterscrollmatrix;
10133                         else
10134                                 matrix = identitymatrix;
10135                         break;
10136                 case Q3TCMOD_ENTITYTRANSLATE:
10137                         // this is used in Q3 to allow the gamecode to control texcoord
10138                         // scrolling on the entity, which is not supported in darkplaces yet.
10139                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10140                         break;
10141                 case Q3TCMOD_ROTATE:
10142                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10143                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10144                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10145                         break;
10146                 case Q3TCMOD_SCALE:
10147                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10148                         break;
10149                 case Q3TCMOD_SCROLL:
10150                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10151                         break;
10152                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10153                         w = (int) tcmod->parms[0];
10154                         h = (int) tcmod->parms[1];
10155                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10156                         f = f - floor(f);
10157                         idx = (int) floor(f * w * h);
10158                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10159                         break;
10160                 case Q3TCMOD_STRETCH:
10161                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10162                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10163                         break;
10164                 case Q3TCMOD_TRANSFORM:
10165                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10166                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10167                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10168                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10169                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10170                         break;
10171                 case Q3TCMOD_TURBULENT:
10172                         // this is handled in the RSurf_PrepareVertices function
10173                         matrix = identitymatrix;
10174                         break;
10175         }
10176         temp = *texmatrix;
10177         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10178 }
10179
10180 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10181 {
10182         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10183         char name[MAX_QPATH];
10184         skinframe_t *skinframe;
10185         unsigned char pixels[296*194];
10186         strlcpy(cache->name, skinname, sizeof(cache->name));
10187         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10188         if (developer_loading.integer)
10189                 Con_Printf("loading %s\n", name);
10190         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10191         if (!skinframe || !skinframe->base)
10192         {
10193                 unsigned char *f;
10194                 fs_offset_t filesize;
10195                 skinframe = NULL;
10196                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10197                 if (f)
10198                 {
10199                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10200                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10201                         Mem_Free(f);
10202                 }
10203         }
10204         cache->skinframe = skinframe;
10205 }
10206
10207 texture_t *R_GetCurrentTexture(texture_t *t)
10208 {
10209         int i;
10210         const entity_render_t *ent = rsurface.entity;
10211         dp_model_t *model = ent->model;
10212         q3shaderinfo_layer_tcmod_t *tcmod;
10213
10214         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10215                 return t->currentframe;
10216         t->update_lastrenderframe = r_textureframe;
10217         t->update_lastrenderentity = (void *)ent;
10218
10219         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10220                 t->camera_entity = ent->entitynumber;
10221         else
10222                 t->camera_entity = 0;
10223
10224         // switch to an alternate material if this is a q1bsp animated material
10225         {
10226                 texture_t *texture = t;
10227                 int s = rsurface.ent_skinnum;
10228                 if ((unsigned int)s >= (unsigned int)model->numskins)
10229                         s = 0;
10230                 if (model->skinscenes)
10231                 {
10232                         if (model->skinscenes[s].framecount > 1)
10233                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10234                         else
10235                                 s = model->skinscenes[s].firstframe;
10236                 }
10237                 if (s > 0)
10238                         t = t + s * model->num_surfaces;
10239                 if (t->animated)
10240                 {
10241                         // use an alternate animation if the entity's frame is not 0,
10242                         // and only if the texture has an alternate animation
10243                         if (rsurface.ent_alttextures && t->anim_total[1])
10244                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10245                         else
10246                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10247                 }
10248                 texture->currentframe = t;
10249         }
10250
10251         // update currentskinframe to be a qw skin or animation frame
10252         if (rsurface.ent_qwskin >= 0)
10253         {
10254                 i = rsurface.ent_qwskin;
10255                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10256                 {
10257                         r_qwskincache_size = cl.maxclients;
10258                         if (r_qwskincache)
10259                                 Mem_Free(r_qwskincache);
10260                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10261                 }
10262                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10263                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10264                 t->currentskinframe = r_qwskincache[i].skinframe;
10265                 if (t->currentskinframe == NULL)
10266                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10267         }
10268         else if (t->numskinframes >= 2)
10269                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10270         if (t->backgroundnumskinframes >= 2)
10271                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10272
10273         t->currentmaterialflags = t->basematerialflags;
10274         t->currentalpha = rsurface.colormod[3];
10275         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10276                 t->currentalpha *= r_wateralpha.value;
10277         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10278                 t->currentalpha *= t->r_water_wateralpha;
10279         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10280                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10281         if (!(rsurface.ent_flags & RENDER_LIGHT))
10282                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10283         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10284         {
10285                 // pick a model lighting mode
10286                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10287                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10288                 else
10289                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10290         }
10291         if (rsurface.ent_flags & RENDER_ADDITIVE)
10292                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10293         else if (t->currentalpha < 1)
10294                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10295         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10296                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10297         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10298                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10299         if (t->backgroundnumskinframes)
10300                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10301         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10302         {
10303                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10304                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10305         }
10306         else
10307                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10308         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10309                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10310
10311         // there is no tcmod
10312         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10313         {
10314                 t->currenttexmatrix = r_waterscrollmatrix;
10315                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10316         }
10317         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10318         {
10319                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10320                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10321         }
10322
10323         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10324                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10325         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10326                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10327
10328         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10329         if (t->currentskinframe->qpixels)
10330                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10331         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10332         if (!t->basetexture)
10333                 t->basetexture = r_texture_notexture;
10334         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10335         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10336         t->nmaptexture = t->currentskinframe->nmap;
10337         if (!t->nmaptexture)
10338                 t->nmaptexture = r_texture_blanknormalmap;
10339         t->glosstexture = r_texture_black;
10340         t->glowtexture = t->currentskinframe->glow;
10341         t->fogtexture = t->currentskinframe->fog;
10342         t->reflectmasktexture = t->currentskinframe->reflect;
10343         if (t->backgroundnumskinframes)
10344         {
10345                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10346                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10347                 t->backgroundglosstexture = r_texture_black;
10348                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10349                 if (!t->backgroundnmaptexture)
10350                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10351         }
10352         else
10353         {
10354                 t->backgroundbasetexture = r_texture_white;
10355                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10356                 t->backgroundglosstexture = r_texture_black;
10357                 t->backgroundglowtexture = NULL;
10358         }
10359         t->specularpower = r_shadow_glossexponent.value;
10360         // TODO: store reference values for these in the texture?
10361         t->specularscale = 0;
10362         if (r_shadow_gloss.integer > 0)
10363         {
10364                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10365                 {
10366                         if (r_shadow_glossintensity.value > 0)
10367                         {
10368                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10369                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10370                                 t->specularscale = r_shadow_glossintensity.value;
10371                         }
10372                 }
10373                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10374                 {
10375                         t->glosstexture = r_texture_white;
10376                         t->backgroundglosstexture = r_texture_white;
10377                         t->specularscale = r_shadow_gloss2intensity.value;
10378                         t->specularpower = r_shadow_gloss2exponent.value;
10379                 }
10380         }
10381         t->specularscale *= t->specularscalemod;
10382         t->specularpower *= t->specularpowermod;
10383
10384         // lightmaps mode looks bad with dlights using actual texturing, so turn
10385         // off the colormap and glossmap, but leave the normalmap on as it still
10386         // accurately represents the shading involved
10387         if (gl_lightmaps.integer)
10388         {
10389                 t->basetexture = r_texture_grey128;
10390                 t->pantstexture = r_texture_black;
10391                 t->shirttexture = r_texture_black;
10392                 t->nmaptexture = r_texture_blanknormalmap;
10393                 t->glosstexture = r_texture_black;
10394                 t->glowtexture = NULL;
10395                 t->fogtexture = NULL;
10396                 t->reflectmasktexture = NULL;
10397                 t->backgroundbasetexture = NULL;
10398                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10399                 t->backgroundglosstexture = r_texture_black;
10400                 t->backgroundglowtexture = NULL;
10401                 t->specularscale = 0;
10402                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10403         }
10404
10405         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10406         VectorClear(t->dlightcolor);
10407         t->currentnumlayers = 0;
10408         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10409         {
10410                 int blendfunc1, blendfunc2;
10411                 qboolean depthmask;
10412                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10413                 {
10414                         blendfunc1 = GL_SRC_ALPHA;
10415                         blendfunc2 = GL_ONE;
10416                 }
10417                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10418                 {
10419                         blendfunc1 = GL_SRC_ALPHA;
10420                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10421                 }
10422                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10423                 {
10424                         blendfunc1 = t->customblendfunc[0];
10425                         blendfunc2 = t->customblendfunc[1];
10426                 }
10427                 else
10428                 {
10429                         blendfunc1 = GL_ONE;
10430                         blendfunc2 = GL_ZERO;
10431                 }
10432                 // don't colormod evilblend textures
10433                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10434                         VectorSet(t->lightmapcolor, 1, 1, 1);
10435                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10436                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10437                 {
10438                         // fullbright is not affected by r_refdef.lightmapintensity
10439                         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]);
10440                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10441                                 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]);
10442                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10443                                 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]);
10444                 }
10445                 else
10446                 {
10447                         vec3_t ambientcolor;
10448                         float colorscale;
10449                         // set the color tint used for lights affecting this surface
10450                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10451                         colorscale = 2;
10452                         // q3bsp has no lightmap updates, so the lightstylevalue that
10453                         // would normally be baked into the lightmap must be
10454                         // applied to the color
10455                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10456                         if (model->type == mod_brushq3)
10457                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10458                         colorscale *= r_refdef.lightmapintensity;
10459                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10460                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10461                         // basic lit geometry
10462                         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]);
10463                         // add pants/shirt if needed
10464                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10465                                 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]);
10466                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10467                                 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]);
10468                         // now add ambient passes if needed
10469                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10470                         {
10471                                 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]);
10472                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10473                                         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]);
10474                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10475                                         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]);
10476                         }
10477                 }
10478                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10479                         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]);
10480                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10481                 {
10482                         // if this is opaque use alpha blend which will darken the earlier
10483                         // passes cheaply.
10484                         //
10485                         // if this is an alpha blended material, all the earlier passes
10486                         // were darkened by fog already, so we only need to add the fog
10487                         // color ontop through the fog mask texture
10488                         //
10489                         // if this is an additive blended material, all the earlier passes
10490                         // were darkened by fog already, and we should not add fog color
10491                         // (because the background was not darkened, there is no fog color
10492                         // that was lost behind it).
10493                         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]);
10494                 }
10495         }
10496
10497         return t->currentframe;
10498 }
10499
10500 rsurfacestate_t rsurface;
10501
10502 void R_Mesh_ResizeArrays(int newvertices)
10503 {
10504         unsigned char *base;
10505         size_t size;
10506         if (rsurface.array_size >= newvertices)
10507                 return;
10508         if (rsurface.array_base)
10509                 Mem_Free(rsurface.array_base);
10510         rsurface.array_size = (newvertices + 1023) & ~1023;
10511         size = 0;
10512         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10513         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10514         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10515         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10516         size += rsurface.array_size * sizeof(float[3]);
10517         size += rsurface.array_size * sizeof(float[3]);
10518         size += rsurface.array_size * sizeof(float[3]);
10519         size += rsurface.array_size * sizeof(float[3]);
10520         size += rsurface.array_size * sizeof(float[3]);
10521         size += rsurface.array_size * sizeof(float[3]);
10522         size += rsurface.array_size * sizeof(float[3]);
10523         size += rsurface.array_size * sizeof(float[3]);
10524         size += rsurface.array_size * sizeof(float[4]);
10525         size += rsurface.array_size * sizeof(float[2]);
10526         size += rsurface.array_size * sizeof(float[2]);
10527         size += rsurface.array_size * sizeof(float[4]);
10528         size += rsurface.array_size * sizeof(int[3]);
10529         size += rsurface.array_size * sizeof(unsigned short[3]);
10530         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10531         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10532         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10533         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10534         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10535         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10536         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10537         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10538         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10539         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10540         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10541         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10542         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10543         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10544         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10545         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10546         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10547         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10548         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10549 }
10550
10551 void RSurf_ActiveWorldEntity(void)
10552 {
10553         dp_model_t *model = r_refdef.scene.worldmodel;
10554         //if (rsurface.entity == r_refdef.scene.worldentity)
10555         //      return;
10556         rsurface.entity = r_refdef.scene.worldentity;
10557         rsurface.skeleton = NULL;
10558         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10559         rsurface.ent_skinnum = 0;
10560         rsurface.ent_qwskin = -1;
10561         rsurface.ent_shadertime = 0;
10562         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10563         if (rsurface.array_size < model->surfmesh.num_vertices)
10564                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10565         rsurface.matrix = identitymatrix;
10566         rsurface.inversematrix = identitymatrix;
10567         rsurface.matrixscale = 1;
10568         rsurface.inversematrixscale = 1;
10569         R_EntityMatrix(&identitymatrix);
10570         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10571         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10572         rsurface.fograngerecip = r_refdef.fograngerecip;
10573         rsurface.fogheightfade = r_refdef.fogheightfade;
10574         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10575         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10576         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10577         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10578         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10579         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10580         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10581         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10582         rsurface.colormod[3] = 1;
10583         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);
10584         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10585         rsurface.frameblend[0].lerp = 1;
10586         rsurface.ent_alttextures = false;
10587         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10588         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10589         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10590         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10591         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10592         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10593         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10594         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10595         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10596         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10597         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10598         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10599         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10600         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10601         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10602         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10603         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10604         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10605         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10606         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10607         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10608         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10609         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10610         rsurface.modelelement3i = model->surfmesh.data_element3i;
10611         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10612         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10613         rsurface.modelelement3s = model->surfmesh.data_element3s;
10614         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10615         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10616         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10617         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10618         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10619         rsurface.modelsurfaces = model->data_surfaces;
10620         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10621         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10622         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10623         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10624         rsurface.modelgeneratedvertex = false;
10625         rsurface.batchgeneratedvertex = false;
10626         rsurface.batchfirstvertex = 0;
10627         rsurface.batchnumvertices = 0;
10628         rsurface.batchfirsttriangle = 0;
10629         rsurface.batchnumtriangles = 0;
10630         rsurface.batchvertex3f  = NULL;
10631         rsurface.batchvertex3f_vertexbuffer = NULL;
10632         rsurface.batchvertex3f_bufferoffset = 0;
10633         rsurface.batchsvector3f = NULL;
10634         rsurface.batchsvector3f_vertexbuffer = NULL;
10635         rsurface.batchsvector3f_bufferoffset = 0;
10636         rsurface.batchtvector3f = NULL;
10637         rsurface.batchtvector3f_vertexbuffer = NULL;
10638         rsurface.batchtvector3f_bufferoffset = 0;
10639         rsurface.batchnormal3f  = NULL;
10640         rsurface.batchnormal3f_vertexbuffer = NULL;
10641         rsurface.batchnormal3f_bufferoffset = 0;
10642         rsurface.batchlightmapcolor4f = NULL;
10643         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10644         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10645         rsurface.batchtexcoordtexture2f = NULL;
10646         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10647         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10648         rsurface.batchtexcoordlightmap2f = NULL;
10649         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10650         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10651         rsurface.batchvertexmesh = NULL;
10652         rsurface.batchvertexmeshbuffer = NULL;
10653         rsurface.batchvertexposition = NULL;
10654         rsurface.batchvertexpositionbuffer = NULL;
10655         rsurface.batchelement3i = NULL;
10656         rsurface.batchelement3i_indexbuffer = NULL;
10657         rsurface.batchelement3i_bufferoffset = 0;
10658         rsurface.batchelement3s = NULL;
10659         rsurface.batchelement3s_indexbuffer = NULL;
10660         rsurface.batchelement3s_bufferoffset = 0;
10661         rsurface.passcolor4f = NULL;
10662         rsurface.passcolor4f_vertexbuffer = NULL;
10663         rsurface.passcolor4f_bufferoffset = 0;
10664 }
10665
10666 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10667 {
10668         dp_model_t *model = ent->model;
10669         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10670         //      return;
10671         rsurface.entity = (entity_render_t *)ent;
10672         rsurface.skeleton = ent->skeleton;
10673         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10674         rsurface.ent_skinnum = ent->skinnum;
10675         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;
10676         rsurface.ent_shadertime = ent->shadertime;
10677         rsurface.ent_flags = ent->flags;
10678         if (rsurface.array_size < model->surfmesh.num_vertices)
10679                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10680         rsurface.matrix = ent->matrix;
10681         rsurface.inversematrix = ent->inversematrix;
10682         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10683         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10684         R_EntityMatrix(&rsurface.matrix);
10685         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10686         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10687         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10688         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10689         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10690         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10691         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10692         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10693         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10694         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10695         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10696         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10697         rsurface.colormod[3] = ent->alpha;
10698         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10699         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10700         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10701         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10702         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10703         if (ent->model->brush.submodel && !prepass)
10704         {
10705                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10706                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10707         }
10708         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10709         {
10710                 if (ent->animcache_vertex3f && !r_framedata_failed)
10711                 {
10712                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10713                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10714                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10715                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10716                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10717                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10718                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10719                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10720                 }
10721                 else if (wanttangents)
10722                 {
10723                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10724                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10725                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10726                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10727                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10728                         rsurface.modelvertexmesh = NULL;
10729                         rsurface.modelvertexmeshbuffer = NULL;
10730                         rsurface.modelvertexposition = NULL;
10731                         rsurface.modelvertexpositionbuffer = NULL;
10732                 }
10733                 else if (wantnormals)
10734                 {
10735                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10736                         rsurface.modelsvector3f = NULL;
10737                         rsurface.modeltvector3f = NULL;
10738                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10739                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10740                         rsurface.modelvertexmesh = NULL;
10741                         rsurface.modelvertexmeshbuffer = NULL;
10742                         rsurface.modelvertexposition = NULL;
10743                         rsurface.modelvertexpositionbuffer = NULL;
10744                 }
10745                 else
10746                 {
10747                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10748                         rsurface.modelsvector3f = NULL;
10749                         rsurface.modeltvector3f = NULL;
10750                         rsurface.modelnormal3f = NULL;
10751                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10752                         rsurface.modelvertexmesh = NULL;
10753                         rsurface.modelvertexmeshbuffer = NULL;
10754                         rsurface.modelvertexposition = NULL;
10755                         rsurface.modelvertexpositionbuffer = NULL;
10756                 }
10757                 rsurface.modelvertex3f_vertexbuffer = 0;
10758                 rsurface.modelvertex3f_bufferoffset = 0;
10759                 rsurface.modelsvector3f_vertexbuffer = 0;
10760                 rsurface.modelsvector3f_bufferoffset = 0;
10761                 rsurface.modeltvector3f_vertexbuffer = 0;
10762                 rsurface.modeltvector3f_bufferoffset = 0;
10763                 rsurface.modelnormal3f_vertexbuffer = 0;
10764                 rsurface.modelnormal3f_bufferoffset = 0;
10765                 rsurface.modelgeneratedvertex = true;
10766         }
10767         else
10768         {
10769                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10770                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10771                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10772                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10773                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10774                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10775                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10776                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10777                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10778                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10779                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10780                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10781                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10782                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10783                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10784                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10785                 rsurface.modelgeneratedvertex = false;
10786         }
10787         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10788         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10789         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10790         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10791         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10792         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10793         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10794         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10795         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10796         rsurface.modelelement3i = model->surfmesh.data_element3i;
10797         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10798         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10799         rsurface.modelelement3s = model->surfmesh.data_element3s;
10800         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10801         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10802         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10803         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10804         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10805         rsurface.modelsurfaces = model->data_surfaces;
10806         rsurface.batchgeneratedvertex = false;
10807         rsurface.batchfirstvertex = 0;
10808         rsurface.batchnumvertices = 0;
10809         rsurface.batchfirsttriangle = 0;
10810         rsurface.batchnumtriangles = 0;
10811         rsurface.batchvertex3f  = NULL;
10812         rsurface.batchvertex3f_vertexbuffer = NULL;
10813         rsurface.batchvertex3f_bufferoffset = 0;
10814         rsurface.batchsvector3f = NULL;
10815         rsurface.batchsvector3f_vertexbuffer = NULL;
10816         rsurface.batchsvector3f_bufferoffset = 0;
10817         rsurface.batchtvector3f = NULL;
10818         rsurface.batchtvector3f_vertexbuffer = NULL;
10819         rsurface.batchtvector3f_bufferoffset = 0;
10820         rsurface.batchnormal3f  = NULL;
10821         rsurface.batchnormal3f_vertexbuffer = NULL;
10822         rsurface.batchnormal3f_bufferoffset = 0;
10823         rsurface.batchlightmapcolor4f = NULL;
10824         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10825         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10826         rsurface.batchtexcoordtexture2f = NULL;
10827         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10828         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10829         rsurface.batchtexcoordlightmap2f = NULL;
10830         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10831         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10832         rsurface.batchvertexmesh = NULL;
10833         rsurface.batchvertexmeshbuffer = NULL;
10834         rsurface.batchvertexposition = NULL;
10835         rsurface.batchvertexpositionbuffer = NULL;
10836         rsurface.batchelement3i = NULL;
10837         rsurface.batchelement3i_indexbuffer = NULL;
10838         rsurface.batchelement3i_bufferoffset = 0;
10839         rsurface.batchelement3s = NULL;
10840         rsurface.batchelement3s_indexbuffer = NULL;
10841         rsurface.batchelement3s_bufferoffset = 0;
10842         rsurface.passcolor4f = NULL;
10843         rsurface.passcolor4f_vertexbuffer = NULL;
10844         rsurface.passcolor4f_bufferoffset = 0;
10845 }
10846
10847 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)
10848 {
10849         int i;
10850
10851         rsurface.entity = r_refdef.scene.worldentity;
10852         rsurface.skeleton = NULL;
10853         rsurface.ent_skinnum = 0;
10854         rsurface.ent_qwskin = -1;
10855         rsurface.ent_shadertime = shadertime;
10856         rsurface.ent_flags = entflags;
10857         rsurface.modelnumvertices = numvertices;
10858         rsurface.modelnumtriangles = numtriangles;
10859         if (rsurface.array_size < rsurface.modelnumvertices)
10860                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10861         rsurface.matrix = *matrix;
10862         rsurface.inversematrix = *inversematrix;
10863         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10864         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10865         R_EntityMatrix(&rsurface.matrix);
10866         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10867         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10868         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10869         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10870         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10871         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10872         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10873         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10874         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10875         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10876         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10877         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10878         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);
10879         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10880         rsurface.frameblend[0].lerp = 1;
10881         rsurface.ent_alttextures = false;
10882         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10883         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10884         if (wanttangents)
10885         {
10886                 rsurface.modelvertex3f = vertex3f;
10887                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10888                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10889                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10890         }
10891         else if (wantnormals)
10892         {
10893                 rsurface.modelvertex3f = vertex3f;
10894                 rsurface.modelsvector3f = NULL;
10895                 rsurface.modeltvector3f = NULL;
10896                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10897         }
10898         else
10899         {
10900                 rsurface.modelvertex3f = vertex3f;
10901                 rsurface.modelsvector3f = NULL;
10902                 rsurface.modeltvector3f = NULL;
10903                 rsurface.modelnormal3f = NULL;
10904         }
10905         rsurface.modelvertexmesh = NULL;
10906         rsurface.modelvertexmeshbuffer = NULL;
10907         rsurface.modelvertexposition = NULL;
10908         rsurface.modelvertexpositionbuffer = NULL;
10909         rsurface.modelvertex3f_vertexbuffer = 0;
10910         rsurface.modelvertex3f_bufferoffset = 0;
10911         rsurface.modelsvector3f_vertexbuffer = 0;
10912         rsurface.modelsvector3f_bufferoffset = 0;
10913         rsurface.modeltvector3f_vertexbuffer = 0;
10914         rsurface.modeltvector3f_bufferoffset = 0;
10915         rsurface.modelnormal3f_vertexbuffer = 0;
10916         rsurface.modelnormal3f_bufferoffset = 0;
10917         rsurface.modelgeneratedvertex = true;
10918         rsurface.modellightmapcolor4f  = color4f;
10919         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10920         rsurface.modellightmapcolor4f_bufferoffset = 0;
10921         rsurface.modeltexcoordtexture2f  = texcoord2f;
10922         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10923         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10924         rsurface.modeltexcoordlightmap2f  = NULL;
10925         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10926         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10927         rsurface.modelelement3i = element3i;
10928         rsurface.modelelement3i_indexbuffer = NULL;
10929         rsurface.modelelement3i_bufferoffset = 0;
10930         rsurface.modelelement3s = element3s;
10931         rsurface.modelelement3s_indexbuffer = NULL;
10932         rsurface.modelelement3s_bufferoffset = 0;
10933         rsurface.modellightmapoffsets = NULL;
10934         rsurface.modelsurfaces = NULL;
10935         rsurface.batchgeneratedvertex = false;
10936         rsurface.batchfirstvertex = 0;
10937         rsurface.batchnumvertices = 0;
10938         rsurface.batchfirsttriangle = 0;
10939         rsurface.batchnumtriangles = 0;
10940         rsurface.batchvertex3f  = NULL;
10941         rsurface.batchvertex3f_vertexbuffer = NULL;
10942         rsurface.batchvertex3f_bufferoffset = 0;
10943         rsurface.batchsvector3f = NULL;
10944         rsurface.batchsvector3f_vertexbuffer = NULL;
10945         rsurface.batchsvector3f_bufferoffset = 0;
10946         rsurface.batchtvector3f = NULL;
10947         rsurface.batchtvector3f_vertexbuffer = NULL;
10948         rsurface.batchtvector3f_bufferoffset = 0;
10949         rsurface.batchnormal3f  = NULL;
10950         rsurface.batchnormal3f_vertexbuffer = NULL;
10951         rsurface.batchnormal3f_bufferoffset = 0;
10952         rsurface.batchlightmapcolor4f = NULL;
10953         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10954         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10955         rsurface.batchtexcoordtexture2f = NULL;
10956         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10957         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10958         rsurface.batchtexcoordlightmap2f = NULL;
10959         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10960         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10961         rsurface.batchvertexmesh = NULL;
10962         rsurface.batchvertexmeshbuffer = NULL;
10963         rsurface.batchvertexposition = NULL;
10964         rsurface.batchvertexpositionbuffer = NULL;
10965         rsurface.batchelement3i = NULL;
10966         rsurface.batchelement3i_indexbuffer = NULL;
10967         rsurface.batchelement3i_bufferoffset = 0;
10968         rsurface.batchelement3s = NULL;
10969         rsurface.batchelement3s_indexbuffer = NULL;
10970         rsurface.batchelement3s_bufferoffset = 0;
10971         rsurface.passcolor4f = NULL;
10972         rsurface.passcolor4f_vertexbuffer = NULL;
10973         rsurface.passcolor4f_bufferoffset = 0;
10974
10975         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10976         {
10977                 if ((wantnormals || wanttangents) && !normal3f)
10978                 {
10979                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10980                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10981                 }
10982                 if (wanttangents && !svector3f)
10983                 {
10984                         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);
10985                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10986                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10987                 }
10988         }
10989
10990         // now convert arrays into vertexmesh structs
10991         for (i = 0;i < numvertices;i++)
10992         {
10993                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10994                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10995                 if (rsurface.modelsvector3f)
10996                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10997                 if (rsurface.modeltvector3f)
10998                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10999                 if (rsurface.modelnormal3f)
11000                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11001                 if (rsurface.modellightmapcolor4f)
11002                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11003                 if (rsurface.modeltexcoordtexture2f)
11004                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11005                 if (rsurface.modeltexcoordlightmap2f)
11006                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11007         }
11008 }
11009
11010 float RSurf_FogPoint(const float *v)
11011 {
11012         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11013         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11014         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11015         float FogHeightFade = r_refdef.fogheightfade;
11016         float fogfrac;
11017         unsigned int fogmasktableindex;
11018         if (r_refdef.fogplaneviewabove)
11019                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11020         else
11021                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11022         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11023         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11024 }
11025
11026 float RSurf_FogVertex(const float *v)
11027 {
11028         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11029         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11030         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11031         float FogHeightFade = rsurface.fogheightfade;
11032         float fogfrac;
11033         unsigned int fogmasktableindex;
11034         if (r_refdef.fogplaneviewabove)
11035                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11036         else
11037                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11038         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11039         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11040 }
11041
11042 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11043 {
11044         int i;
11045         for (i = 0;i < numelements;i++)
11046                 outelement3i[i] = inelement3i[i] + adjust;
11047 }
11048
11049 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11050 extern cvar_t gl_vbo;
11051 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11052 {
11053         int deformindex;
11054         int firsttriangle;
11055         int numtriangles;
11056         int firstvertex;
11057         int endvertex;
11058         int numvertices;
11059         int surfacefirsttriangle;
11060         int surfacenumtriangles;
11061         int surfacefirstvertex;
11062         int surfaceendvertex;
11063         int surfacenumvertices;
11064         int needsupdate;
11065         int i, j;
11066         qboolean gaps;
11067         qboolean dynamicvertex;
11068         float amplitude;
11069         float animpos;
11070         float scale;
11071         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11072         float waveparms[4];
11073         q3shaderinfo_deform_t *deform;
11074         const msurface_t *surface, *firstsurface;
11075         r_vertexposition_t *vertexposition;
11076         r_vertexmesh_t *vertexmesh;
11077         if (!texturenumsurfaces)
11078                 return;
11079         // find vertex range of this surface batch
11080         gaps = false;
11081         firstsurface = texturesurfacelist[0];
11082         firsttriangle = firstsurface->num_firsttriangle;
11083         numtriangles = 0;
11084         firstvertex = endvertex = firstsurface->num_firstvertex;
11085         for (i = 0;i < texturenumsurfaces;i++)
11086         {
11087                 surface = texturesurfacelist[i];
11088                 if (surface != firstsurface + i)
11089                         gaps = true;
11090                 surfacefirstvertex = surface->num_firstvertex;
11091                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11092                 surfacenumtriangles = surface->num_triangles;
11093                 if (firstvertex > surfacefirstvertex)
11094                         firstvertex = surfacefirstvertex;
11095                 if (endvertex < surfaceendvertex)
11096                         endvertex = surfaceendvertex;
11097                 numtriangles += surfacenumtriangles;
11098         }
11099         if (!numtriangles)
11100                 return;
11101
11102         // we now know the vertex range used, and if there are any gaps in it
11103         rsurface.batchfirstvertex = firstvertex;
11104         rsurface.batchnumvertices = endvertex - firstvertex;
11105         rsurface.batchfirsttriangle = firsttriangle;
11106         rsurface.batchnumtriangles = numtriangles;
11107
11108         // this variable holds flags for which properties have been updated that
11109         // may require regenerating vertexmesh or vertexposition arrays...
11110         needsupdate = 0;
11111
11112         // check if any dynamic vertex processing must occur
11113         dynamicvertex = false;
11114
11115         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11116                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11117         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11118         {
11119                 switch (deform->deform)
11120                 {
11121                 default:
11122                 case Q3DEFORM_PROJECTIONSHADOW:
11123                 case Q3DEFORM_TEXT0:
11124                 case Q3DEFORM_TEXT1:
11125                 case Q3DEFORM_TEXT2:
11126                 case Q3DEFORM_TEXT3:
11127                 case Q3DEFORM_TEXT4:
11128                 case Q3DEFORM_TEXT5:
11129                 case Q3DEFORM_TEXT6:
11130                 case Q3DEFORM_TEXT7:
11131                 case Q3DEFORM_NONE:
11132                         break;
11133                 case Q3DEFORM_AUTOSPRITE:
11134                         dynamicvertex = true;
11135                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11136                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11137                         break;
11138                 case Q3DEFORM_AUTOSPRITE2:
11139                         dynamicvertex = true;
11140                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11141                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11142                         break;
11143                 case Q3DEFORM_NORMAL:
11144                         dynamicvertex = true;
11145                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11146                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11147                         break;
11148                 case Q3DEFORM_WAVE:
11149                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11150                                 break; // if wavefunc is a nop, ignore this transform
11151                         dynamicvertex = true;
11152                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11153                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11154                         break;
11155                 case Q3DEFORM_BULGE:
11156                         dynamicvertex = true;
11157                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11158                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11159                         break;
11160                 case Q3DEFORM_MOVE:
11161                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11162                                 break; // if wavefunc is a nop, ignore this transform
11163                         dynamicvertex = true;
11164                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11165                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11166                         break;
11167                 }
11168         }
11169         switch(rsurface.texture->tcgen.tcgen)
11170         {
11171         default:
11172         case Q3TCGEN_TEXTURE:
11173                 break;
11174         case Q3TCGEN_LIGHTMAP:
11175                 dynamicvertex = true;
11176                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11177                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11178                 break;
11179         case Q3TCGEN_VECTOR:
11180                 dynamicvertex = true;
11181                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11182                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11183                 break;
11184         case Q3TCGEN_ENVIRONMENT:
11185                 dynamicvertex = true;
11186                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11187                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11188                 break;
11189         }
11190         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11191         {
11192                 dynamicvertex = true;
11193                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11194                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11195         }
11196
11197         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11198         {
11199                 dynamicvertex = true;
11200                 batchneed |= BATCHNEED_NOGAPS;
11201                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11202         }
11203
11204         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11205         {
11206                 dynamicvertex = true;
11207                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11208                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11209         }
11210
11211         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11212         {
11213                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11214                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11215                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11216                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11217                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11218                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11219                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11220         }
11221
11222         // when the model data has no vertex buffer (dynamic mesh), we need to
11223         // eliminate gaps
11224         if (!rsurface.modelvertexmeshbuffer)
11225                 batchneed |= BATCHNEED_NOGAPS;
11226
11227         // if needsupdate, we have to do a dynamic vertex batch for sure
11228         if (needsupdate & batchneed)
11229                 dynamicvertex = true;
11230
11231         // see if we need to build vertexmesh from arrays
11232         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11233                 dynamicvertex = true;
11234
11235         // see if we need to build vertexposition from arrays
11236         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11237                 dynamicvertex = true;
11238
11239         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11240         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11241                 dynamicvertex = true;
11242
11243         // if there is a chance of animated vertex colors, it's a dynamic batch
11244         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11245                 dynamicvertex = true;
11246
11247         rsurface.batchvertex3f = rsurface.modelvertex3f;
11248         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11249         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11250         rsurface.batchsvector3f = rsurface.modelsvector3f;
11251         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11252         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11253         rsurface.batchtvector3f = rsurface.modeltvector3f;
11254         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11255         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11256         rsurface.batchnormal3f = rsurface.modelnormal3f;
11257         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11258         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11259         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11260         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11261         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11262         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11263         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11264         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11265         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11266         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11267         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11268         rsurface.batchvertexposition = rsurface.modelvertexposition;
11269         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11270         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11271         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11272         rsurface.batchelement3i = rsurface.modelelement3i;
11273         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11274         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11275         rsurface.batchelement3s = rsurface.modelelement3s;
11276         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11277         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11278
11279         // if any dynamic vertex processing has to occur in software, we copy the
11280         // entire surface list together before processing to rebase the vertices
11281         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11282         //
11283         // if any gaps exist and we do not have a static vertex buffer, we have to
11284         // copy the surface list together to avoid wasting upload bandwidth on the
11285         // vertices in the gaps.
11286         //
11287         // if gaps exist and we have a static vertex buffer, we still have to
11288         // combine the index buffer ranges into one dynamic index buffer.
11289         //
11290         // in all cases we end up with data that can be drawn in one call.
11291
11292         if (!dynamicvertex)
11293         {
11294                 // static vertex data, just set pointers...
11295                 rsurface.batchgeneratedvertex = false;
11296                 // if there are gaps, we want to build a combined index buffer,
11297                 // otherwise use the original static buffer with an appropriate offset
11298                 if (gaps)
11299                 {
11300                         firsttriangle = 0;
11301                         numtriangles = 0;
11302                         for (i = 0;i < texturenumsurfaces;i++)
11303                         {
11304                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11305                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11306                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11307                                 numtriangles += surfacenumtriangles;
11308                         }
11309                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11310                         rsurface.batchelement3i_indexbuffer = NULL;
11311                         rsurface.batchelement3i_bufferoffset = 0;
11312                         rsurface.batchelement3s = NULL;
11313                         rsurface.batchelement3s_indexbuffer = NULL;
11314                         rsurface.batchelement3s_bufferoffset = 0;
11315                         if (endvertex <= 65536)
11316                         {
11317                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11318                                 for (i = 0;i < numtriangles*3;i++)
11319                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11320                         }
11321                         rsurface.batchfirsttriangle = firsttriangle;
11322                         rsurface.batchnumtriangles = numtriangles;
11323                 }
11324                 return;
11325         }
11326
11327         // something needs software processing, do it for real...
11328         // we only directly handle interleaved array data in this case...
11329         rsurface.batchgeneratedvertex = true;
11330
11331         // now copy the vertex data into a combined array and make an index array
11332         // (this is what Quake3 does all the time)
11333         //if (gaps || rsurface.batchfirstvertex)
11334         {
11335                 rsurface.batchvertexposition = NULL;
11336                 rsurface.batchvertexpositionbuffer = NULL;
11337                 rsurface.batchvertexmesh = NULL;
11338                 rsurface.batchvertexmeshbuffer = NULL;
11339                 rsurface.batchvertex3f = NULL;
11340                 rsurface.batchvertex3f_vertexbuffer = NULL;
11341                 rsurface.batchvertex3f_bufferoffset = 0;
11342                 rsurface.batchsvector3f = NULL;
11343                 rsurface.batchsvector3f_vertexbuffer = NULL;
11344                 rsurface.batchsvector3f_bufferoffset = 0;
11345                 rsurface.batchtvector3f = NULL;
11346                 rsurface.batchtvector3f_vertexbuffer = NULL;
11347                 rsurface.batchtvector3f_bufferoffset = 0;
11348                 rsurface.batchnormal3f = NULL;
11349                 rsurface.batchnormal3f_vertexbuffer = NULL;
11350                 rsurface.batchnormal3f_bufferoffset = 0;
11351                 rsurface.batchlightmapcolor4f = NULL;
11352                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11353                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11354                 rsurface.batchtexcoordtexture2f = NULL;
11355                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11356                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11357                 rsurface.batchtexcoordlightmap2f = NULL;
11358                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11359                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11360                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11361                 rsurface.batchelement3i_indexbuffer = NULL;
11362                 rsurface.batchelement3i_bufferoffset = 0;
11363                 rsurface.batchelement3s = NULL;
11364                 rsurface.batchelement3s_indexbuffer = NULL;
11365                 rsurface.batchelement3s_bufferoffset = 0;
11366                 // we'll only be setting up certain arrays as needed
11367                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11368                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11369                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11370                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11371                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11372                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11373                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11374                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11375                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11376                 {
11377                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11378                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11379                 }
11380                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11381                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11382                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11383                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11384                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11385                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11386                 numvertices = 0;
11387                 numtriangles = 0;
11388                 for (i = 0;i < texturenumsurfaces;i++)
11389                 {
11390                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11391                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11392                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11393                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11394                         // copy only the data requested
11395                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11396                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11397                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11398                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11399                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11400                         {
11401                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11402                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11403                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11404                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11405                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11406                                 {
11407                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11408                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11409                                 }
11410                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11411                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11412                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11413                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11414                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11415                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11416                         }
11417                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11418                         numvertices += surfacenumvertices;
11419                         numtriangles += surfacenumtriangles;
11420                 }
11421
11422                 // generate a 16bit index array as well if possible
11423                 // (in general, dynamic batches fit)
11424                 if (numvertices <= 65536)
11425                 {
11426                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11427                         for (i = 0;i < numtriangles*3;i++)
11428                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11429                 }
11430
11431                 // since we've copied everything, the batch now starts at 0
11432                 rsurface.batchfirstvertex = 0;
11433                 rsurface.batchnumvertices = numvertices;
11434                 rsurface.batchfirsttriangle = 0;
11435                 rsurface.batchnumtriangles = numtriangles;
11436         }
11437
11438         // q1bsp surfaces rendered in vertex color mode have to have colors
11439         // calculated based on lightstyles
11440         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11441         {
11442                 // generate color arrays for the surfaces in this list
11443                 int c[4];
11444                 int scale;
11445                 int size3;
11446                 const int *offsets;
11447                 const unsigned char *lm;
11448                 numvertices = 0;
11449                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11450                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11451                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11452                 for (i = 0;i < texturenumsurfaces;i++)
11453                 {
11454                         surface = texturesurfacelist[i];
11455                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11456                         surfacenumvertices = surface->num_vertices;
11457                         if (surface->lightmapinfo->samples)
11458                         {
11459                                 for (j = 0;j < surfacenumvertices;j++)
11460                                 {
11461                                         lm = surface->lightmapinfo->samples + offsets[j];
11462                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11463                                         VectorScale(lm, scale, c);
11464                                         if (surface->lightmapinfo->styles[1] != 255)
11465                                         {
11466                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11467                                                 lm += size3;
11468                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11469                                                 VectorMA(c, scale, lm, c);
11470                                                 if (surface->lightmapinfo->styles[2] != 255)
11471                                                 {
11472                                                         lm += size3;
11473                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11474                                                         VectorMA(c, scale, lm, c);
11475                                                         if (surface->lightmapinfo->styles[3] != 255)
11476                                                         {
11477                                                                 lm += size3;
11478                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11479                                                                 VectorMA(c, scale, lm, c);
11480                                                         }
11481                                                 }
11482                                         }
11483                                         c[0] >>= 15;
11484                                         c[1] >>= 15;
11485                                         c[2] >>= 15;
11486                                         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);
11487                                         numvertices++;
11488                                 }
11489                         }
11490                         else
11491                         {
11492                                 for (j = 0;j < surfacenumvertices;j++)
11493                                 {
11494                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11495                                         numvertices++;
11496                                 }
11497                         }
11498                 }
11499         }
11500
11501         // if vertices are deformed (sprite flares and things in maps, possibly
11502         // water waves, bulges and other deformations), modify the copied vertices
11503         // in place
11504         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11505         {
11506                 switch (deform->deform)
11507                 {
11508                 default:
11509                 case Q3DEFORM_PROJECTIONSHADOW:
11510                 case Q3DEFORM_TEXT0:
11511                 case Q3DEFORM_TEXT1:
11512                 case Q3DEFORM_TEXT2:
11513                 case Q3DEFORM_TEXT3:
11514                 case Q3DEFORM_TEXT4:
11515                 case Q3DEFORM_TEXT5:
11516                 case Q3DEFORM_TEXT6:
11517                 case Q3DEFORM_TEXT7:
11518                 case Q3DEFORM_NONE:
11519                         break;
11520                 case Q3DEFORM_AUTOSPRITE:
11521                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11522                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11523                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11524                         VectorNormalize(newforward);
11525                         VectorNormalize(newright);
11526                         VectorNormalize(newup);
11527                         // a single autosprite surface can contain multiple sprites...
11528                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11529                         {
11530                                 VectorClear(center);
11531                                 for (i = 0;i < 4;i++)
11532                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11533                                 VectorScale(center, 0.25f, center);
11534                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11535                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11536                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11537                                 for (i = 0;i < 4;i++)
11538                                 {
11539                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11540                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11541                                 }
11542                         }
11543                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11544                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11545                         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);
11546                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11547                         rsurface.batchvertex3f_vertexbuffer = NULL;
11548                         rsurface.batchvertex3f_bufferoffset = 0;
11549                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11550                         rsurface.batchsvector3f_vertexbuffer = NULL;
11551                         rsurface.batchsvector3f_bufferoffset = 0;
11552                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11553                         rsurface.batchtvector3f_vertexbuffer = NULL;
11554                         rsurface.batchtvector3f_bufferoffset = 0;
11555                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11556                         rsurface.batchnormal3f_vertexbuffer = NULL;
11557                         rsurface.batchnormal3f_bufferoffset = 0;
11558                         break;
11559                 case Q3DEFORM_AUTOSPRITE2:
11560                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11561                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11562                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11563                         VectorNormalize(newforward);
11564                         VectorNormalize(newright);
11565                         VectorNormalize(newup);
11566                         {
11567                                 const float *v1, *v2;
11568                                 vec3_t start, end;
11569                                 float f, l;
11570                                 struct
11571                                 {
11572                                         float length2;
11573                                         const float *v1;
11574                                         const float *v2;
11575                                 }
11576                                 shortest[2];
11577                                 memset(shortest, 0, sizeof(shortest));
11578                                 // a single autosprite surface can contain multiple sprites...
11579                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11580                                 {
11581                                         VectorClear(center);
11582                                         for (i = 0;i < 4;i++)
11583                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11584                                         VectorScale(center, 0.25f, center);
11585                                         // find the two shortest edges, then use them to define the
11586                                         // axis vectors for rotating around the central axis
11587                                         for (i = 0;i < 6;i++)
11588                                         {
11589                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11590                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11591                                                 l = VectorDistance2(v1, v2);
11592                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11593                                                 if (v1[2] != v2[2])
11594                                                         l += (1.0f / 1024.0f);
11595                                                 if (shortest[0].length2 > l || i == 0)
11596                                                 {
11597                                                         shortest[1] = shortest[0];
11598                                                         shortest[0].length2 = l;
11599                                                         shortest[0].v1 = v1;
11600                                                         shortest[0].v2 = v2;
11601                                                 }
11602                                                 else if (shortest[1].length2 > l || i == 1)
11603                                                 {
11604                                                         shortest[1].length2 = l;
11605                                                         shortest[1].v1 = v1;
11606                                                         shortest[1].v2 = v2;
11607                                                 }
11608                                         }
11609                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11610                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11611                                         // this calculates the right vector from the shortest edge
11612                                         // and the up vector from the edge midpoints
11613                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11614                                         VectorNormalize(right);
11615                                         VectorSubtract(end, start, up);
11616                                         VectorNormalize(up);
11617                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11618                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11619                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11620                                         VectorNegate(forward, forward);
11621                                         VectorReflect(forward, 0, up, forward);
11622                                         VectorNormalize(forward);
11623                                         CrossProduct(up, forward, newright);
11624                                         VectorNormalize(newright);
11625                                         // rotate the quad around the up axis vector, this is made
11626                                         // especially easy by the fact we know the quad is flat,
11627                                         // so we only have to subtract the center position and
11628                                         // measure distance along the right vector, and then
11629                                         // multiply that by the newright vector and add back the
11630                                         // center position
11631                                         // we also need to subtract the old position to undo the
11632                                         // displacement from the center, which we do with a
11633                                         // DotProduct, the subtraction/addition of center is also
11634                                         // optimized into DotProducts here
11635                                         l = DotProduct(right, center);
11636                                         for (i = 0;i < 4;i++)
11637                                         {
11638                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11639                                                 f = DotProduct(right, v1) - l;
11640                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11641                                         }
11642                                 }
11643                         }
11644                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11645                         rsurface.batchvertex3f_vertexbuffer = NULL;
11646                         rsurface.batchvertex3f_bufferoffset = 0;
11647                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11648                         {
11649                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11650                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11651                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11652                                 rsurface.batchnormal3f_bufferoffset = 0;
11653                         }
11654                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11655                         {
11656                                 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);
11657                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11658                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11659                                 rsurface.batchsvector3f_bufferoffset = 0;
11660                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11661                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11662                                 rsurface.batchtvector3f_bufferoffset = 0;
11663                         }
11664                         break;
11665                 case Q3DEFORM_NORMAL:
11666                         // deform the normals to make reflections wavey
11667                         for (j = 0;j < rsurface.batchnumvertices;j++)
11668                         {
11669                                 float vertex[3];
11670                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11671                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11672                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11673                                 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]);
11674                                 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]);
11675                                 VectorNormalize(normal);
11676                         }
11677                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11678                         rsurface.batchnormal3f_vertexbuffer = NULL;
11679                         rsurface.batchnormal3f_bufferoffset = 0;
11680                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11681                         {
11682                                 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);
11683                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11684                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11685                                 rsurface.batchsvector3f_bufferoffset = 0;
11686                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11687                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11688                                 rsurface.batchtvector3f_bufferoffset = 0;
11689                         }
11690                         break;
11691                 case Q3DEFORM_WAVE:
11692                         // deform vertex array to make wavey water and flags and such
11693                         waveparms[0] = deform->waveparms[0];
11694                         waveparms[1] = deform->waveparms[1];
11695                         waveparms[2] = deform->waveparms[2];
11696                         waveparms[3] = deform->waveparms[3];
11697                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11698                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11699                         // this is how a divisor of vertex influence on deformation
11700                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11701                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11702                         for (j = 0;j < rsurface.batchnumvertices;j++)
11703                         {
11704                                 // if the wavefunc depends on time, evaluate it per-vertex
11705                                 if (waveparms[3])
11706                                 {
11707                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11708                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11709                                 }
11710                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11711                         }
11712                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11713                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11714                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11715                         rsurface.batchvertex3f_vertexbuffer = NULL;
11716                         rsurface.batchvertex3f_bufferoffset = 0;
11717                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11718                         rsurface.batchnormal3f_vertexbuffer = NULL;
11719                         rsurface.batchnormal3f_bufferoffset = 0;
11720                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11721                         {
11722                                 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);
11723                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11724                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11725                                 rsurface.batchsvector3f_bufferoffset = 0;
11726                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11727                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11728                                 rsurface.batchtvector3f_bufferoffset = 0;
11729                         }
11730                         break;
11731                 case Q3DEFORM_BULGE:
11732                         // deform vertex array to make the surface have moving bulges
11733                         for (j = 0;j < rsurface.batchnumvertices;j++)
11734                         {
11735                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11736                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11737                         }
11738                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11739                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11740                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11741                         rsurface.batchvertex3f_vertexbuffer = NULL;
11742                         rsurface.batchvertex3f_bufferoffset = 0;
11743                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11744                         rsurface.batchnormal3f_vertexbuffer = NULL;
11745                         rsurface.batchnormal3f_bufferoffset = 0;
11746                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11747                         {
11748                                 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);
11749                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11750                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11751                                 rsurface.batchsvector3f_bufferoffset = 0;
11752                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11753                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11754                                 rsurface.batchtvector3f_bufferoffset = 0;
11755                         }
11756                         break;
11757                 case Q3DEFORM_MOVE:
11758                         // deform vertex array
11759                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11760                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11761                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11762                         VectorScale(deform->parms, scale, waveparms);
11763                         for (j = 0;j < rsurface.batchnumvertices;j++)
11764                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11765                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11766                         rsurface.batchvertex3f_vertexbuffer = NULL;
11767                         rsurface.batchvertex3f_bufferoffset = 0;
11768                         break;
11769                 }
11770         }
11771
11772         // generate texcoords based on the chosen texcoord source
11773         switch(rsurface.texture->tcgen.tcgen)
11774         {
11775         default:
11776         case Q3TCGEN_TEXTURE:
11777                 break;
11778         case Q3TCGEN_LIGHTMAP:
11779                 if (rsurface.batchtexcoordlightmap2f)
11780                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11781                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11782                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11783                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11784                 break;
11785         case Q3TCGEN_VECTOR:
11786                 for (j = 0;j < rsurface.batchnumvertices;j++)
11787                 {
11788                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11789                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11790                 }
11791                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11792                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11793                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11794                 break;
11795         case Q3TCGEN_ENVIRONMENT:
11796                 // make environment reflections using a spheremap
11797                 for (j = 0;j < rsurface.batchnumvertices;j++)
11798                 {
11799                         // identical to Q3A's method, but executed in worldspace so
11800                         // carried models can be shiny too
11801
11802                         float viewer[3], d, reflected[3], worldreflected[3];
11803
11804                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11805                         // VectorNormalize(viewer);
11806
11807                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11808
11809                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11810                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11811                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11812                         // note: this is proportinal to viewer, so we can normalize later
11813
11814                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11815                         VectorNormalize(worldreflected);
11816
11817                         // note: this sphere map only uses world x and z!
11818                         // so positive and negative y will LOOK THE SAME.
11819                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11820                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11821                 }
11822                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11823                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11824                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11825                 break;
11826         }
11827         // the only tcmod that needs software vertex processing is turbulent, so
11828         // check for it here and apply the changes if needed
11829         // and we only support that as the first one
11830         // (handling a mixture of turbulent and other tcmods would be problematic
11831         //  without punting it entirely to a software path)
11832         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11833         {
11834                 amplitude = rsurface.texture->tcmods[0].parms[1];
11835                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11836                 for (j = 0;j < rsurface.batchnumvertices;j++)
11837                 {
11838                         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);
11839                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11840                 }
11841                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11842                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11843                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11844         }
11845
11846         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11847         {
11848                 // convert the modified arrays to vertex structs
11849                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11850                 rsurface.batchvertexmeshbuffer = NULL;
11851                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11852                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11853                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11854                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11855                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11856                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11857                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11858                 {
11859                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11860                         {
11861                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11862                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11863                         }
11864                 }
11865                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11866                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11867                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11868                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11869                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11870                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11871                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11872                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11873                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11874         }
11875
11876         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11877         {
11878                 // convert the modified arrays to vertex structs
11879                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11880                 rsurface.batchvertexpositionbuffer = NULL;
11881                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11882                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11883                 else
11884                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11885                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11886         }
11887 }
11888
11889 void RSurf_DrawBatch(void)
11890 {
11891         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);
11892 }
11893
11894 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11895 {
11896         // pick the closest matching water plane
11897         int planeindex, vertexindex, bestplaneindex = -1;
11898         float d, bestd;
11899         vec3_t vert;
11900         const float *v;
11901         r_waterstate_waterplane_t *p;
11902         bestd = 0;
11903         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11904         {
11905                 if(p->camera_entity != rsurface.texture->camera_entity)
11906                         continue;
11907                 d = 0;
11908                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11909                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11910                 {
11911                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11912                         d += fabs(PlaneDiff(vert, &p->plane));
11913                 }
11914                 if (bestd > d || bestplaneindex < 0)
11915                 {
11916                         bestd = d;
11917                         bestplaneindex = planeindex;
11918                 }
11919         }
11920         return bestplaneindex;
11921 }
11922
11923 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11924 {
11925         int i;
11926         for (i = 0;i < rsurface.batchnumvertices;i++)
11927                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11928         rsurface.passcolor4f = rsurface.array_passcolor4f;
11929         rsurface.passcolor4f_vertexbuffer = 0;
11930         rsurface.passcolor4f_bufferoffset = 0;
11931 }
11932
11933 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11934 {
11935         int i;
11936         float f;
11937         const float *v;
11938         const float *c;
11939         float *c2;
11940         if (rsurface.passcolor4f)
11941         {
11942                 // generate color arrays
11943                 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)
11944                 {
11945                         f = RSurf_FogVertex(v);
11946                         c2[0] = c[0] * f;
11947                         c2[1] = c[1] * f;
11948                         c2[2] = c[2] * f;
11949                         c2[3] = c[3];
11950                 }
11951         }
11952         else
11953         {
11954                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11955                 {
11956                         f = RSurf_FogVertex(v);
11957                         c2[0] = f;
11958                         c2[1] = f;
11959                         c2[2] = f;
11960                         c2[3] = 1;
11961                 }
11962         }
11963         rsurface.passcolor4f = rsurface.array_passcolor4f;
11964         rsurface.passcolor4f_vertexbuffer = 0;
11965         rsurface.passcolor4f_bufferoffset = 0;
11966 }
11967
11968 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11969 {
11970         int i;
11971         float f;
11972         const float *v;
11973         const float *c;
11974         float *c2;
11975         if (!rsurface.passcolor4f)
11976                 return;
11977         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)
11978         {
11979                 f = RSurf_FogVertex(v);
11980                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11981                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11982                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11983                 c2[3] = c[3];
11984         }
11985         rsurface.passcolor4f = rsurface.array_passcolor4f;
11986         rsurface.passcolor4f_vertexbuffer = 0;
11987         rsurface.passcolor4f_bufferoffset = 0;
11988 }
11989
11990 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11991 {
11992         int i;
11993         const float *c;
11994         float *c2;
11995         if (!rsurface.passcolor4f)
11996                 return;
11997         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11998         {
11999                 c2[0] = c[0] * r;
12000                 c2[1] = c[1] * g;
12001                 c2[2] = c[2] * b;
12002                 c2[3] = c[3] * a;
12003         }
12004         rsurface.passcolor4f = rsurface.array_passcolor4f;
12005         rsurface.passcolor4f_vertexbuffer = 0;
12006         rsurface.passcolor4f_bufferoffset = 0;
12007 }
12008
12009 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12010 {
12011         int i;
12012         const float *c;
12013         float *c2;
12014         if (!rsurface.passcolor4f)
12015                 return;
12016         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12017         {
12018                 c2[0] = c[0] + r_refdef.scene.ambient;
12019                 c2[1] = c[1] + r_refdef.scene.ambient;
12020                 c2[2] = c[2] + r_refdef.scene.ambient;
12021                 c2[3] = c[3];
12022         }
12023         rsurface.passcolor4f = rsurface.array_passcolor4f;
12024         rsurface.passcolor4f_vertexbuffer = 0;
12025         rsurface.passcolor4f_bufferoffset = 0;
12026 }
12027
12028 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12029 {
12030         // TODO: optimize
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         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12039         RSurf_DrawBatch();
12040 }
12041
12042 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12043 {
12044         // TODO: optimize applyfog && applycolor case
12045         // just apply fog if necessary, and tint the fog color array if necessary
12046         rsurface.passcolor4f = NULL;
12047         rsurface.passcolor4f_vertexbuffer = 0;
12048         rsurface.passcolor4f_bufferoffset = 0;
12049         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12050         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12051         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12052         GL_Color(r, g, b, a);
12053         RSurf_DrawBatch();
12054 }
12055
12056 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12057 {
12058         // TODO: optimize
12059         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12060         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12061         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12062         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12063         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12064         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12065         GL_Color(r, g, b, a);
12066         RSurf_DrawBatch();
12067 }
12068
12069 static void RSurf_DrawBatch_GL11_ClampColor(void)
12070 {
12071         int i;
12072         const float *c1;
12073         float *c2;
12074         if (!rsurface.passcolor4f)
12075                 return;
12076         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12077         {
12078                 c2[0] = bound(0.0f, c1[0], 1.0f);
12079                 c2[1] = bound(0.0f, c1[1], 1.0f);
12080                 c2[2] = bound(0.0f, c1[2], 1.0f);
12081                 c2[3] = bound(0.0f, c1[3], 1.0f);
12082         }
12083 }
12084
12085 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12086 {
12087         int i;
12088         float f;
12089         float alpha;
12090         const float *v;
12091         const float *n;
12092         float *c;
12093         vec3_t ambientcolor;
12094         vec3_t diffusecolor;
12095         vec3_t lightdir;
12096         // TODO: optimize
12097         // model lighting
12098         VectorCopy(rsurface.modellight_lightdir, lightdir);
12099         f = 0.5f * r_refdef.lightmapintensity;
12100         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12101         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12102         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12103         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12104         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12105         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12106         alpha = *a;
12107         if (VectorLength2(diffusecolor) > 0)
12108         {
12109                 // q3-style directional shading
12110                 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)
12111                 {
12112                         if ((f = DotProduct(n, lightdir)) > 0)
12113                                 VectorMA(ambientcolor, f, diffusecolor, c);
12114                         else
12115                                 VectorCopy(ambientcolor, c);
12116                         c[3] = alpha;
12117                 }
12118                 *r = 1;
12119                 *g = 1;
12120                 *b = 1;
12121                 *a = 1;
12122                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12123                 rsurface.passcolor4f_vertexbuffer = 0;
12124                 rsurface.passcolor4f_bufferoffset = 0;
12125                 *applycolor = false;
12126         }
12127         else
12128         {
12129                 *r = ambientcolor[0];
12130                 *g = ambientcolor[1];
12131                 *b = ambientcolor[2];
12132                 rsurface.passcolor4f = NULL;
12133                 rsurface.passcolor4f_vertexbuffer = 0;
12134                 rsurface.passcolor4f_bufferoffset = 0;
12135         }
12136 }
12137
12138 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12139 {
12140         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12141         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12142         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12143         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12144         GL_Color(r, g, b, a);
12145         RSurf_DrawBatch();
12146 }
12147
12148 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12149 {
12150         int i;
12151         float f;
12152         const float *v;
12153         float *c;
12154         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12155         {
12156                 f = 1 - RSurf_FogVertex(v);
12157                 c[0] = r;
12158                 c[1] = g;
12159                 c[2] = b;
12160                 c[3] = f * a;
12161         }
12162 }
12163
12164 void RSurf_SetupDepthAndCulling(void)
12165 {
12166         // submodels are biased to avoid z-fighting with world surfaces that they
12167         // may be exactly overlapping (avoids z-fighting artifacts on certain
12168         // doors and things in Quake maps)
12169         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12170         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12171         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12172         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12173 }
12174
12175 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12176 {
12177         // transparent sky would be ridiculous
12178         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12179                 return;
12180         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12181         skyrenderlater = true;
12182         RSurf_SetupDepthAndCulling();
12183         GL_DepthMask(true);
12184         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12185         // skymasking on them, and Quake3 never did sky masking (unlike
12186         // software Quake and software Quake2), so disable the sky masking
12187         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12188         // and skymasking also looks very bad when noclipping outside the
12189         // level, so don't use it then either.
12190         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12191         {
12192                 R_Mesh_ResetTextureState();
12193                 if (skyrendermasked)
12194                 {
12195                         R_SetupShader_DepthOrShadow();
12196                         // depth-only (masking)
12197                         GL_ColorMask(0,0,0,0);
12198                         // just to make sure that braindead drivers don't draw
12199                         // anything despite that colormask...
12200                         GL_BlendFunc(GL_ZERO, GL_ONE);
12201                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12202                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12203                 }
12204                 else
12205                 {
12206                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12207                         // fog sky
12208                         GL_BlendFunc(GL_ONE, GL_ZERO);
12209                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12210                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12211                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12212                 }
12213                 RSurf_DrawBatch();
12214                 if (skyrendermasked)
12215                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12216         }
12217         R_Mesh_ResetTextureState();
12218         GL_Color(1, 1, 1, 1);
12219 }
12220
12221 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12222 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12223 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12224 {
12225         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12226                 return;
12227         if (prepass)
12228         {
12229                 // render screenspace normalmap to texture
12230                 GL_DepthMask(true);
12231                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12232                 RSurf_DrawBatch();
12233                 return;
12234         }
12235
12236         // bind lightmap texture
12237
12238         // water/refraction/reflection/camera surfaces have to be handled specially
12239         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12240         {
12241                 int start, end, startplaneindex;
12242                 for (start = 0;start < texturenumsurfaces;start = end)
12243                 {
12244                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12245                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12246                                 ;
12247                         // now that we have a batch using the same planeindex, render it
12248                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12249                         {
12250                                 // render water or distortion background
12251                                 GL_DepthMask(true);
12252                                 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));
12253                                 RSurf_DrawBatch();
12254                                 // blend surface on top
12255                                 GL_DepthMask(false);
12256                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12257                                 RSurf_DrawBatch();
12258                         }
12259                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12260                         {
12261                                 // render surface with reflection texture as input
12262                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12263                                 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));
12264                                 RSurf_DrawBatch();
12265                         }
12266                 }
12267                 return;
12268         }
12269
12270         // render surface batch normally
12271         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12272         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12273         RSurf_DrawBatch();
12274 }
12275
12276 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12277 {
12278         // OpenGL 1.3 path - anything not completely ancient
12279         qboolean applycolor;
12280         qboolean applyfog;
12281         int layerindex;
12282         const texturelayer_t *layer;
12283         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);
12284         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12285
12286         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12287         {
12288                 vec4_t layercolor;
12289                 int layertexrgbscale;
12290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12291                 {
12292                         if (layerindex == 0)
12293                                 GL_AlphaTest(true);
12294                         else
12295                         {
12296                                 GL_AlphaTest(false);
12297                                 GL_DepthFunc(GL_EQUAL);
12298                         }
12299                 }
12300                 GL_DepthMask(layer->depthmask && writedepth);
12301                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12302                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12303                 {
12304                         layertexrgbscale = 4;
12305                         VectorScale(layer->color, 0.25f, layercolor);
12306                 }
12307                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12308                 {
12309                         layertexrgbscale = 2;
12310                         VectorScale(layer->color, 0.5f, layercolor);
12311                 }
12312                 else
12313                 {
12314                         layertexrgbscale = 1;
12315                         VectorScale(layer->color, 1.0f, layercolor);
12316                 }
12317                 layercolor[3] = layer->color[3];
12318                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12319                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12320                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12321                 switch (layer->type)
12322                 {
12323                 case TEXTURELAYERTYPE_LITTEXTURE:
12324                         // single-pass lightmapped texture with 2x rgbscale
12325                         R_Mesh_TexBind(0, r_texture_white);
12326                         R_Mesh_TexMatrix(0, NULL);
12327                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12328                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12329                         R_Mesh_TexBind(1, layer->texture);
12330                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12331                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12332                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12333                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12334                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12335                         else if (rsurface.uselightmaptexture)
12336                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12337                         else
12338                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12339                         break;
12340                 case TEXTURELAYERTYPE_TEXTURE:
12341                         // singletexture unlit texture with transparency support
12342                         R_Mesh_TexBind(0, layer->texture);
12343                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12344                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12345                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12346                         R_Mesh_TexBind(1, 0);
12347                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12348                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12349                         break;
12350                 case TEXTURELAYERTYPE_FOG:
12351                         // singletexture fogging
12352                         if (layer->texture)
12353                         {
12354                                 R_Mesh_TexBind(0, layer->texture);
12355                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12356                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12357                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12358                         }
12359                         else
12360                         {
12361                                 R_Mesh_TexBind(0, 0);
12362                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12363                         }
12364                         R_Mesh_TexBind(1, 0);
12365                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12366                         // generate a color array for the fog pass
12367                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12368                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12369                         RSurf_DrawBatch();
12370                         break;
12371                 default:
12372                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12373                 }
12374         }
12375         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12376         {
12377                 GL_DepthFunc(GL_LEQUAL);
12378                 GL_AlphaTest(false);
12379         }
12380 }
12381
12382 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12383 {
12384         // OpenGL 1.1 - crusty old voodoo path
12385         qboolean applyfog;
12386         int layerindex;
12387         const texturelayer_t *layer;
12388         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);
12389         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12390
12391         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12392         {
12393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12394                 {
12395                         if (layerindex == 0)
12396                                 GL_AlphaTest(true);
12397                         else
12398                         {
12399                                 GL_AlphaTest(false);
12400                                 GL_DepthFunc(GL_EQUAL);
12401                         }
12402                 }
12403                 GL_DepthMask(layer->depthmask && writedepth);
12404                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12405                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12406                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12407                 switch (layer->type)
12408                 {
12409                 case TEXTURELAYERTYPE_LITTEXTURE:
12410                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12411                         {
12412                                 // two-pass lit texture with 2x rgbscale
12413                                 // first the lightmap pass
12414                                 R_Mesh_TexBind(0, r_texture_white);
12415                                 R_Mesh_TexMatrix(0, NULL);
12416                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12417                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12418                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12419                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12420                                 else if (rsurface.uselightmaptexture)
12421                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12422                                 else
12423                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12424                                 // then apply the texture to it
12425                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12426                                 R_Mesh_TexBind(0, layer->texture);
12427                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12428                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12429                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12430                                 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);
12431                         }
12432                         else
12433                         {
12434                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12435                                 R_Mesh_TexBind(0, layer->texture);
12436                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12437                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12438                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12439                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12440                                         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);
12441                                 else
12442                                         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);
12443                         }
12444                         break;
12445                 case TEXTURELAYERTYPE_TEXTURE:
12446                         // singletexture unlit texture with transparency support
12447                         R_Mesh_TexBind(0, layer->texture);
12448                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12449                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12450                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12451                         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);
12452                         break;
12453                 case TEXTURELAYERTYPE_FOG:
12454                         // singletexture fogging
12455                         if (layer->texture)
12456                         {
12457                                 R_Mesh_TexBind(0, layer->texture);
12458                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12459                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12460                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12461                         }
12462                         else
12463                         {
12464                                 R_Mesh_TexBind(0, 0);
12465                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12466                         }
12467                         // generate a color array for the fog pass
12468                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12469                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12470                         RSurf_DrawBatch();
12471                         break;
12472                 default:
12473                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12474                 }
12475         }
12476         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12477         {
12478                 GL_DepthFunc(GL_LEQUAL);
12479                 GL_AlphaTest(false);
12480         }
12481 }
12482
12483 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12484 {
12485         int vi;
12486         int j;
12487         r_vertexgeneric_t *batchvertex;
12488         float c[4];
12489
12490         GL_AlphaTest(false);
12491         R_Mesh_ResetTextureState();
12492         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12493
12494         if(rsurface.texture && rsurface.texture->currentskinframe)
12495         {
12496                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12497                 c[3] *= rsurface.texture->currentalpha;
12498         }
12499         else
12500         {
12501                 c[0] = 1;
12502                 c[1] = 0;
12503                 c[2] = 1;
12504                 c[3] = 1;
12505         }
12506
12507         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12508         {
12509                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12510                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12511                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12512         }
12513
12514         // brighten it up (as texture value 127 means "unlit")
12515         c[0] *= 2 * r_refdef.view.colorscale;
12516         c[1] *= 2 * r_refdef.view.colorscale;
12517         c[2] *= 2 * r_refdef.view.colorscale;
12518
12519         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12520                 c[3] *= r_wateralpha.value;
12521
12522         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12523         {
12524                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12525                 GL_DepthMask(false);
12526         }
12527         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12528         {
12529                 GL_BlendFunc(GL_ONE, GL_ONE);
12530                 GL_DepthMask(false);
12531         }
12532         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12533         {
12534                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12535                 GL_DepthMask(false);
12536         }
12537         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12538         {
12539                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12540                 GL_DepthMask(false);
12541         }
12542         else
12543         {
12544                 GL_BlendFunc(GL_ONE, GL_ZERO);
12545                 GL_DepthMask(writedepth);
12546         }
12547
12548         if (r_showsurfaces.integer == 3)
12549         {
12550                 rsurface.passcolor4f = NULL;
12551
12552                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12553                 {
12554                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12555
12556                         rsurface.passcolor4f = NULL;
12557                         rsurface.passcolor4f_vertexbuffer = 0;
12558                         rsurface.passcolor4f_bufferoffset = 0;
12559                 }
12560                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12561                 {
12562                         qboolean applycolor = true;
12563                         float one = 1.0;
12564
12565                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12566
12567                         r_refdef.lightmapintensity = 1;
12568                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12569                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12570                 }
12571                 else
12572                 {
12573                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12574
12575                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12576                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12577                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12578                 }
12579
12580                 if(!rsurface.passcolor4f)
12581                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12582
12583                 RSurf_DrawBatch_GL11_ApplyAmbient();
12584                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12585                 if(r_refdef.fogenabled)
12586                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12587                 RSurf_DrawBatch_GL11_ClampColor();
12588
12589                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12590                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12591                 RSurf_DrawBatch();
12592         }
12593         else if (!r_refdef.view.showdebug)
12594         {
12595                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12596                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12597                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12598                 {
12599                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12600                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12601                 }
12602                 R_Mesh_PrepareVertices_Generic_Unlock();
12603                 RSurf_DrawBatch();
12604         }
12605         else if (r_showsurfaces.integer == 4)
12606         {
12607                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12608                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12609                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12610                 {
12611                         unsigned char c = vi << 3;
12612                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12613                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12614                 }
12615                 R_Mesh_PrepareVertices_Generic_Unlock();
12616                 RSurf_DrawBatch();
12617         }
12618         else if (r_showsurfaces.integer == 2)
12619         {
12620                 const int *e;
12621                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12622                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12623                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12624                 {
12625                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12626                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12627                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12628                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12629                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12630                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12631                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12632                 }
12633                 R_Mesh_PrepareVertices_Generic_Unlock();
12634                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12635         }
12636         else
12637         {
12638                 int texturesurfaceindex;
12639                 int k;
12640                 const msurface_t *surface;
12641                 unsigned char surfacecolor4ub[4];
12642                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12643                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12644                 vi = 0;
12645                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12646                 {
12647                         surface = texturesurfacelist[texturesurfaceindex];
12648                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12649                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12650                         for (j = 0;j < surface->num_vertices;j++)
12651                         {
12652                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12653                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12654                                 vi++;
12655                         }
12656                 }
12657                 R_Mesh_PrepareVertices_Generic_Unlock();
12658                 RSurf_DrawBatch();
12659         }
12660 }
12661
12662 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12663 {
12664         CHECKGLERROR
12665         RSurf_SetupDepthAndCulling();
12666         if (r_showsurfaces.integer)
12667         {
12668                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12669                 return;
12670         }
12671         switch (vid.renderpath)
12672         {
12673         case RENDERPATH_GL20:
12674         case RENDERPATH_CGGL:
12675         case RENDERPATH_D3D9:
12676         case RENDERPATH_D3D10:
12677         case RENDERPATH_D3D11:
12678                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12679                 break;
12680         case RENDERPATH_GL13:
12681                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12682                 break;
12683         case RENDERPATH_GL11:
12684                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12685                 break;
12686         }
12687         CHECKGLERROR
12688 }
12689
12690 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12691 {
12692         CHECKGLERROR
12693         RSurf_SetupDepthAndCulling();
12694         if (r_showsurfaces.integer)
12695         {
12696                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12697                 return;
12698         }
12699         switch (vid.renderpath)
12700         {
12701         case RENDERPATH_GL20:
12702         case RENDERPATH_CGGL:
12703         case RENDERPATH_D3D9:
12704         case RENDERPATH_D3D10:
12705         case RENDERPATH_D3D11:
12706                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12707                 break;
12708         case RENDERPATH_GL13:
12709                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12710                 break;
12711         case RENDERPATH_GL11:
12712                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12713                 break;
12714         }
12715         CHECKGLERROR
12716 }
12717
12718 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12719 {
12720         int i, j;
12721         int texturenumsurfaces, endsurface;
12722         texture_t *texture;
12723         const msurface_t *surface;
12724 #define MAXBATCH_TRANSPARENTSURFACES 256
12725         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12726
12727         // if the model is static it doesn't matter what value we give for
12728         // wantnormals and wanttangents, so this logic uses only rules applicable
12729         // to a model, knowing that they are meaningless otherwise
12730         if (ent == r_refdef.scene.worldentity)
12731                 RSurf_ActiveWorldEntity();
12732         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12733                 RSurf_ActiveModelEntity(ent, false, false, false);
12734         else
12735         {
12736                 switch (vid.renderpath)
12737                 {
12738                 case RENDERPATH_GL20:
12739                 case RENDERPATH_CGGL:
12740                 case RENDERPATH_D3D9:
12741                 case RENDERPATH_D3D10:
12742                 case RENDERPATH_D3D11:
12743                         RSurf_ActiveModelEntity(ent, true, true, false);
12744                         break;
12745                 case RENDERPATH_GL13:
12746                 case RENDERPATH_GL11:
12747                         RSurf_ActiveModelEntity(ent, true, false, false);
12748                         break;
12749                 }
12750         }
12751
12752         if (r_transparentdepthmasking.integer)
12753         {
12754                 qboolean setup = false;
12755                 for (i = 0;i < numsurfaces;i = j)
12756                 {
12757                         j = i + 1;
12758                         surface = rsurface.modelsurfaces + surfacelist[i];
12759                         texture = surface->texture;
12760                         rsurface.texture = R_GetCurrentTexture(texture);
12761                         rsurface.lightmaptexture = NULL;
12762                         rsurface.deluxemaptexture = NULL;
12763                         rsurface.uselightmaptexture = false;
12764                         // scan ahead until we find a different texture
12765                         endsurface = min(i + 1024, numsurfaces);
12766                         texturenumsurfaces = 0;
12767                         texturesurfacelist[texturenumsurfaces++] = surface;
12768                         for (;j < endsurface;j++)
12769                         {
12770                                 surface = rsurface.modelsurfaces + surfacelist[j];
12771                                 if (texture != surface->texture)
12772                                         break;
12773                                 texturesurfacelist[texturenumsurfaces++] = surface;
12774                         }
12775                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12776                                 continue;
12777                         // render the range of surfaces as depth
12778                         if (!setup)
12779                         {
12780                                 setup = true;
12781                                 GL_ColorMask(0,0,0,0);
12782                                 GL_Color(1,1,1,1);
12783                                 GL_DepthTest(true);
12784                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12785                                 GL_DepthMask(true);
12786                                 GL_AlphaTest(false);
12787                                 R_Mesh_ResetTextureState();
12788                                 R_SetupShader_DepthOrShadow();
12789                         }
12790                         RSurf_SetupDepthAndCulling();
12791                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12792                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12793                         RSurf_DrawBatch();
12794                 }
12795                 if (setup)
12796                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12797         }
12798
12799         for (i = 0;i < numsurfaces;i = j)
12800         {
12801                 j = i + 1;
12802                 surface = rsurface.modelsurfaces + surfacelist[i];
12803                 texture = surface->texture;
12804                 rsurface.texture = R_GetCurrentTexture(texture);
12805                 rsurface.lightmaptexture = surface->lightmaptexture;
12806                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12807                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12808                 // scan ahead until we find a different texture
12809                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12810                 texturenumsurfaces = 0;
12811                 texturesurfacelist[texturenumsurfaces++] = surface;
12812                 for (;j < endsurface;j++)
12813                 {
12814                         surface = rsurface.modelsurfaces + surfacelist[j];
12815                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12816                                 break;
12817                         texturesurfacelist[texturenumsurfaces++] = surface;
12818                 }
12819                 // render the range of surfaces
12820                 if (ent == r_refdef.scene.worldentity)
12821                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12822                 else
12823                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12824         }
12825         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12826         GL_AlphaTest(false);
12827 }
12828
12829 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12830 {
12831         // transparent surfaces get pushed off into the transparent queue
12832         int surfacelistindex;
12833         const msurface_t *surface;
12834         vec3_t tempcenter, center;
12835         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12836         {
12837                 surface = texturesurfacelist[surfacelistindex];
12838                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12839                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12840                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12841                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12842                 if (queueentity->transparent_offset) // transparent offset
12843                 {
12844                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12845                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12846                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12847                 }
12848                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12849         }
12850 }
12851
12852 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12853 {
12854         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12855                 return;
12856         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12857                 return;
12858         RSurf_SetupDepthAndCulling();
12859         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12860         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12861         RSurf_DrawBatch();
12862 }
12863
12864 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12865 {
12866         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12867         CHECKGLERROR
12868         if (depthonly)
12869                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12870         else if (prepass)
12871         {
12872                 if (!rsurface.texture->currentnumlayers)
12873                         return;
12874                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12875                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12876                 else
12877                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12878         }
12879         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12880                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12881         else if (!rsurface.texture->currentnumlayers)
12882                 return;
12883         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12884         {
12885                 // in the deferred case, transparent surfaces were queued during prepass
12886                 if (!r_shadow_usingdeferredprepass)
12887                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12888         }
12889         else
12890         {
12891                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12892                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12893         }
12894         CHECKGLERROR
12895 }
12896
12897 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12898 {
12899         int i, j;
12900         texture_t *texture;
12901         // break the surface list down into batches by texture and use of lightmapping
12902         for (i = 0;i < numsurfaces;i = j)
12903         {
12904                 j = i + 1;
12905                 // texture is the base texture pointer, rsurface.texture is the
12906                 // current frame/skin the texture is directing us to use (for example
12907                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12908                 // use skin 1 instead)
12909                 texture = surfacelist[i]->texture;
12910                 rsurface.texture = R_GetCurrentTexture(texture);
12911                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12912                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12913                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12914                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12915                 {
12916                         // if this texture is not the kind we want, skip ahead to the next one
12917                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12918                                 ;
12919                         continue;
12920                 }
12921                 // simply scan ahead until we find a different texture or lightmap state
12922                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12923                         ;
12924                 // render the range of surfaces
12925                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12926         }
12927 }
12928
12929 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12930 {
12931         CHECKGLERROR
12932         if (depthonly)
12933                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12934         else if (prepass)
12935         {
12936                 if (!rsurface.texture->currentnumlayers)
12937                         return;
12938                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12939                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12940                 else
12941                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12942         }
12943         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12944                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12945         else if (!rsurface.texture->currentnumlayers)
12946                 return;
12947         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12948         {
12949                 // in the deferred case, transparent surfaces were queued during prepass
12950                 if (!r_shadow_usingdeferredprepass)
12951                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12952         }
12953         else
12954         {
12955                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12956                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12957         }
12958         CHECKGLERROR
12959 }
12960
12961 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12962 {
12963         int i, j;
12964         texture_t *texture;
12965         // break the surface list down into batches by texture and use of lightmapping
12966         for (i = 0;i < numsurfaces;i = j)
12967         {
12968                 j = i + 1;
12969                 // texture is the base texture pointer, rsurface.texture is the
12970                 // current frame/skin the texture is directing us to use (for example
12971                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12972                 // use skin 1 instead)
12973                 texture = surfacelist[i]->texture;
12974                 rsurface.texture = R_GetCurrentTexture(texture);
12975                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12976                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12977                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12978                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12979                 {
12980                         // if this texture is not the kind we want, skip ahead to the next one
12981                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12982                                 ;
12983                         continue;
12984                 }
12985                 // simply scan ahead until we find a different texture or lightmap state
12986                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12987                         ;
12988                 // render the range of surfaces
12989                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12990         }
12991 }
12992
12993 float locboxvertex3f[6*4*3] =
12994 {
12995         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12996         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12997         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12998         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12999         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13000         1,0,0, 0,0,0, 0,1,0, 1,1,0
13001 };
13002
13003 unsigned short locboxelements[6*2*3] =
13004 {
13005          0, 1, 2, 0, 2, 3,
13006          4, 5, 6, 4, 6, 7,
13007          8, 9,10, 8,10,11,
13008         12,13,14, 12,14,15,
13009         16,17,18, 16,18,19,
13010         20,21,22, 20,22,23
13011 };
13012
13013 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13014 {
13015         int i, j;
13016         cl_locnode_t *loc = (cl_locnode_t *)ent;
13017         vec3_t mins, size;
13018         float vertex3f[6*4*3];
13019         CHECKGLERROR
13020         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13021         GL_DepthMask(false);
13022         GL_DepthRange(0, 1);
13023         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13024         GL_DepthTest(true);
13025         GL_CullFace(GL_NONE);
13026         R_EntityMatrix(&identitymatrix);
13027
13028         R_Mesh_ResetTextureState();
13029
13030         i = surfacelist[0];
13031         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13032                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13033                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13034                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13035
13036         if (VectorCompare(loc->mins, loc->maxs))
13037         {
13038                 VectorSet(size, 2, 2, 2);
13039                 VectorMA(loc->mins, -0.5f, size, mins);
13040         }
13041         else
13042         {
13043                 VectorCopy(loc->mins, mins);
13044                 VectorSubtract(loc->maxs, loc->mins, size);
13045         }
13046
13047         for (i = 0;i < 6*4*3;)
13048                 for (j = 0;j < 3;j++, i++)
13049                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13050
13051         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13052         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13053         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13054 }
13055
13056 void R_DrawLocs(void)
13057 {
13058         int index;
13059         cl_locnode_t *loc, *nearestloc;
13060         vec3_t center;
13061         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13062         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13063         {
13064                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13065                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13066         }
13067 }
13068
13069 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13070 {
13071         if (decalsystem->decals)
13072                 Mem_Free(decalsystem->decals);
13073         memset(decalsystem, 0, sizeof(*decalsystem));
13074 }
13075
13076 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)
13077 {
13078         tridecal_t *decal;
13079         tridecal_t *decals;
13080         int i;
13081
13082         // expand or initialize the system
13083         if (decalsystem->maxdecals <= decalsystem->numdecals)
13084         {
13085                 decalsystem_t old = *decalsystem;
13086                 qboolean useshortelements;
13087                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13088                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13089                 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)));
13090                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13091                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13092                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13093                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13094                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13095                 if (decalsystem->numdecals)
13096                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13097                 if (old.decals)
13098                         Mem_Free(old.decals);
13099                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13100                         decalsystem->element3i[i] = i;
13101                 if (useshortelements)
13102                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13103                                 decalsystem->element3s[i] = i;
13104         }
13105
13106         // grab a decal and search for another free slot for the next one
13107         decals = decalsystem->decals;
13108         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13109         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13110                 ;
13111         decalsystem->freedecal = i;
13112         if (decalsystem->numdecals <= i)
13113                 decalsystem->numdecals = i + 1;
13114
13115         // initialize the decal
13116         decal->lived = 0;
13117         decal->triangleindex = triangleindex;
13118         decal->surfaceindex = surfaceindex;
13119         decal->decalsequence = decalsequence;
13120         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13121         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13122         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13123         decal->color4ub[0][3] = 255;
13124         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13125         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13126         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13127         decal->color4ub[1][3] = 255;
13128         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13129         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13130         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13131         decal->color4ub[2][3] = 255;
13132         decal->vertex3f[0][0] = v0[0];
13133         decal->vertex3f[0][1] = v0[1];
13134         decal->vertex3f[0][2] = v0[2];
13135         decal->vertex3f[1][0] = v1[0];
13136         decal->vertex3f[1][1] = v1[1];
13137         decal->vertex3f[1][2] = v1[2];
13138         decal->vertex3f[2][0] = v2[0];
13139         decal->vertex3f[2][1] = v2[1];
13140         decal->vertex3f[2][2] = v2[2];
13141         decal->texcoord2f[0][0] = t0[0];
13142         decal->texcoord2f[0][1] = t0[1];
13143         decal->texcoord2f[1][0] = t1[0];
13144         decal->texcoord2f[1][1] = t1[1];
13145         decal->texcoord2f[2][0] = t2[0];
13146         decal->texcoord2f[2][1] = t2[1];
13147 }
13148
13149 extern cvar_t cl_decals_bias;
13150 extern cvar_t cl_decals_models;
13151 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13152 // baseparms, parms, temps
13153 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)
13154 {
13155         int cornerindex;
13156         int index;
13157         float v[9][3];
13158         const float *vertex3f;
13159         int numpoints;
13160         float points[2][9][3];
13161         float temp[3];
13162         float tc[9][2];
13163         float f;
13164         float c[9][4];
13165         const int *e;
13166
13167         e = rsurface.modelelement3i + 3*triangleindex;
13168
13169         vertex3f = rsurface.modelvertex3f;
13170
13171         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13172         {
13173                 index = 3*e[cornerindex];
13174                 VectorCopy(vertex3f + index, v[cornerindex]);
13175         }
13176         // cull backfaces
13177         //TriangleNormal(v[0], v[1], v[2], normal);
13178         //if (DotProduct(normal, localnormal) < 0.0f)
13179         //      continue;
13180         // clip by each of the box planes formed from the projection matrix
13181         // if anything survives, we emit the decal
13182         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]);
13183         if (numpoints < 3)
13184                 return;
13185         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]);
13186         if (numpoints < 3)
13187                 return;
13188         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]);
13189         if (numpoints < 3)
13190                 return;
13191         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]);
13192         if (numpoints < 3)
13193                 return;
13194         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]);
13195         if (numpoints < 3)
13196                 return;
13197         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]);
13198         if (numpoints < 3)
13199                 return;
13200         // some part of the triangle survived, so we have to accept it...
13201         if (dynamic)
13202         {
13203                 // dynamic always uses the original triangle
13204                 numpoints = 3;
13205                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13206                 {
13207                         index = 3*e[cornerindex];
13208                         VectorCopy(vertex3f + index, v[cornerindex]);
13209                 }
13210         }
13211         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13212         {
13213                 // convert vertex positions to texcoords
13214                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13215                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13216                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13217                 // calculate distance fade from the projection origin
13218                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13219                 f = bound(0.0f, f, 1.0f);
13220                 c[cornerindex][0] = r * f;
13221                 c[cornerindex][1] = g * f;
13222                 c[cornerindex][2] = b * f;
13223                 c[cornerindex][3] = 1.0f;
13224                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13225         }
13226         if (dynamic)
13227                 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);
13228         else
13229                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13230                         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);
13231 }
13232 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)
13233 {
13234         matrix4x4_t projection;
13235         decalsystem_t *decalsystem;
13236         qboolean dynamic;
13237         dp_model_t *model;
13238         const msurface_t *surface;
13239         const msurface_t *surfaces;
13240         const int *surfacelist;
13241         const texture_t *texture;
13242         int numtriangles;
13243         int numsurfacelist;
13244         int surfacelistindex;
13245         int surfaceindex;
13246         int triangleindex;
13247         float localorigin[3];
13248         float localnormal[3];
13249         float localmins[3];
13250         float localmaxs[3];
13251         float localsize;
13252         //float normal[3];
13253         float planes[6][4];
13254         float angles[3];
13255         bih_t *bih;
13256         int bih_triangles_count;
13257         int bih_triangles[256];
13258         int bih_surfaces[256];
13259
13260         decalsystem = &ent->decalsystem;
13261         model = ent->model;
13262         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13263         {
13264                 R_DecalSystem_Reset(&ent->decalsystem);
13265                 return;
13266         }
13267
13268         if (!model->brush.data_leafs && !cl_decals_models.integer)
13269         {
13270                 if (decalsystem->model)
13271                         R_DecalSystem_Reset(decalsystem);
13272                 return;
13273         }
13274
13275         if (decalsystem->model != model)
13276                 R_DecalSystem_Reset(decalsystem);
13277         decalsystem->model = model;
13278
13279         RSurf_ActiveModelEntity(ent, false, false, false);
13280
13281         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13282         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13283         VectorNormalize(localnormal);
13284         localsize = worldsize*rsurface.inversematrixscale;
13285         localmins[0] = localorigin[0] - localsize;
13286         localmins[1] = localorigin[1] - localsize;
13287         localmins[2] = localorigin[2] - localsize;
13288         localmaxs[0] = localorigin[0] + localsize;
13289         localmaxs[1] = localorigin[1] + localsize;
13290         localmaxs[2] = localorigin[2] + localsize;
13291
13292         //VectorCopy(localnormal, planes[4]);
13293         //VectorVectors(planes[4], planes[2], planes[0]);
13294         AnglesFromVectors(angles, localnormal, NULL, false);
13295         AngleVectors(angles, planes[0], planes[2], planes[4]);
13296         VectorNegate(planes[0], planes[1]);
13297         VectorNegate(planes[2], planes[3]);
13298         VectorNegate(planes[4], planes[5]);
13299         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13300         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13301         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13302         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13303         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13304         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13305
13306 #if 1
13307 // works
13308 {
13309         matrix4x4_t forwardprojection;
13310         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13311         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13312 }
13313 #else
13314 // broken
13315 {
13316         float projectionvector[4][3];
13317         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13318         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13319         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13320         projectionvector[0][0] = planes[0][0] * ilocalsize;
13321         projectionvector[0][1] = planes[1][0] * ilocalsize;
13322         projectionvector[0][2] = planes[2][0] * ilocalsize;
13323         projectionvector[1][0] = planes[0][1] * ilocalsize;
13324         projectionvector[1][1] = planes[1][1] * ilocalsize;
13325         projectionvector[1][2] = planes[2][1] * ilocalsize;
13326         projectionvector[2][0] = planes[0][2] * ilocalsize;
13327         projectionvector[2][1] = planes[1][2] * ilocalsize;
13328         projectionvector[2][2] = planes[2][2] * ilocalsize;
13329         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13330         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13331         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13332         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13333 }
13334 #endif
13335
13336         dynamic = model->surfmesh.isanimated;
13337         numsurfacelist = model->nummodelsurfaces;
13338         surfacelist = model->sortedmodelsurfaces;
13339         surfaces = model->data_surfaces;
13340
13341         bih = NULL;
13342         bih_triangles_count = -1;
13343         if(!dynamic)
13344         {
13345                 if(model->render_bih.numleafs)
13346                         bih = &model->render_bih;
13347                 else if(model->collision_bih.numleafs)
13348                         bih = &model->collision_bih;
13349         }
13350         if(bih)
13351                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13352         if(bih_triangles_count == 0)
13353                 return;
13354         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13355                 return;
13356         if(bih_triangles_count > 0)
13357         {
13358                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13359                 {
13360                         surfaceindex = bih_surfaces[triangleindex];
13361                         surface = surfaces + surfaceindex;
13362                         texture = surface->texture;
13363                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13364                                 continue;
13365                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13366                                 continue;
13367                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13368                 }
13369         }
13370         else
13371         {
13372                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13373                 {
13374                         surfaceindex = surfacelist[surfacelistindex];
13375                         surface = surfaces + surfaceindex;
13376                         // check cull box first because it rejects more than any other check
13377                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13378                                 continue;
13379                         // skip transparent surfaces
13380                         texture = surface->texture;
13381                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13382                                 continue;
13383                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13384                                 continue;
13385                         numtriangles = surface->num_triangles;
13386                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13387                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13388                 }
13389         }
13390 }
13391
13392 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13393 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)
13394 {
13395         int renderentityindex;
13396         float worldmins[3];
13397         float worldmaxs[3];
13398         entity_render_t *ent;
13399
13400         if (!cl_decals_newsystem.integer)
13401                 return;
13402
13403         worldmins[0] = worldorigin[0] - worldsize;
13404         worldmins[1] = worldorigin[1] - worldsize;
13405         worldmins[2] = worldorigin[2] - worldsize;
13406         worldmaxs[0] = worldorigin[0] + worldsize;
13407         worldmaxs[1] = worldorigin[1] + worldsize;
13408         worldmaxs[2] = worldorigin[2] + worldsize;
13409
13410         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13411
13412         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13413         {
13414                 ent = r_refdef.scene.entities[renderentityindex];
13415                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13416                         continue;
13417
13418                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13419         }
13420 }
13421
13422 typedef struct r_decalsystem_splatqueue_s
13423 {
13424         vec3_t worldorigin;
13425         vec3_t worldnormal;
13426         float color[4];
13427         float tcrange[4];
13428         float worldsize;
13429         int decalsequence;
13430 }
13431 r_decalsystem_splatqueue_t;
13432
13433 int r_decalsystem_numqueued = 0;
13434 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13435
13436 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)
13437 {
13438         r_decalsystem_splatqueue_t *queue;
13439
13440         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13441                 return;
13442
13443         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13444         VectorCopy(worldorigin, queue->worldorigin);
13445         VectorCopy(worldnormal, queue->worldnormal);
13446         Vector4Set(queue->color, r, g, b, a);
13447         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13448         queue->worldsize = worldsize;
13449         queue->decalsequence = cl.decalsequence++;
13450 }
13451
13452 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13453 {
13454         int i;
13455         r_decalsystem_splatqueue_t *queue;
13456
13457         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13458                 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);
13459         r_decalsystem_numqueued = 0;
13460 }
13461
13462 extern cvar_t cl_decals_max;
13463 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13464 {
13465         int i;
13466         decalsystem_t *decalsystem = &ent->decalsystem;
13467         int numdecals;
13468         int killsequence;
13469         tridecal_t *decal;
13470         float frametime;
13471         float lifetime;
13472
13473         if (!decalsystem->numdecals)
13474                 return;
13475
13476         if (r_showsurfaces.integer)
13477                 return;
13478
13479         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13480         {
13481                 R_DecalSystem_Reset(decalsystem);
13482                 return;
13483         }
13484
13485         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13486         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13487
13488         if (decalsystem->lastupdatetime)
13489                 frametime = (cl.time - decalsystem->lastupdatetime);
13490         else
13491                 frametime = 0;
13492         decalsystem->lastupdatetime = cl.time;
13493         decal = decalsystem->decals;
13494         numdecals = decalsystem->numdecals;
13495
13496         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13497         {
13498                 if (decal->color4ub[0][3])
13499                 {
13500                         decal->lived += frametime;
13501                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13502                         {
13503                                 memset(decal, 0, sizeof(*decal));
13504                                 if (decalsystem->freedecal > i)
13505                                         decalsystem->freedecal = i;
13506                         }
13507                 }
13508         }
13509         decal = decalsystem->decals;
13510         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13511                 numdecals--;
13512
13513         // collapse the array by shuffling the tail decals into the gaps
13514         for (;;)
13515         {
13516                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13517                         decalsystem->freedecal++;
13518                 if (decalsystem->freedecal == numdecals)
13519                         break;
13520                 decal[decalsystem->freedecal] = decal[--numdecals];
13521         }
13522
13523         decalsystem->numdecals = numdecals;
13524
13525         if (numdecals <= 0)
13526         {
13527                 // if there are no decals left, reset decalsystem
13528                 R_DecalSystem_Reset(decalsystem);
13529         }
13530 }
13531
13532 extern skinframe_t *decalskinframe;
13533 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13534 {
13535         int i;
13536         decalsystem_t *decalsystem = &ent->decalsystem;
13537         int numdecals;
13538         tridecal_t *decal;
13539         float faderate;
13540         float alpha;
13541         float *v3f;
13542         float *c4f;
13543         float *t2f;
13544         const int *e;
13545         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13546         int numtris = 0;
13547
13548         numdecals = decalsystem->numdecals;
13549         if (!numdecals)
13550                 return;
13551
13552         if (r_showsurfaces.integer)
13553                 return;
13554
13555         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13556         {
13557                 R_DecalSystem_Reset(decalsystem);
13558                 return;
13559         }
13560
13561         // if the model is static it doesn't matter what value we give for
13562         // wantnormals and wanttangents, so this logic uses only rules applicable
13563         // to a model, knowing that they are meaningless otherwise
13564         if (ent == r_refdef.scene.worldentity)
13565                 RSurf_ActiveWorldEntity();
13566         else
13567                 RSurf_ActiveModelEntity(ent, false, false, false);
13568
13569         decalsystem->lastupdatetime = cl.time;
13570         decal = decalsystem->decals;
13571
13572         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13573
13574         // update vertex positions for animated models
13575         v3f = decalsystem->vertex3f;
13576         c4f = decalsystem->color4f;
13577         t2f = decalsystem->texcoord2f;
13578         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13579         {
13580                 if (!decal->color4ub[0][3])
13581                         continue;
13582
13583                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13584                         continue;
13585
13586                 // update color values for fading decals
13587                 if (decal->lived >= cl_decals_time.value)
13588                 {
13589                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13590                         alpha *= (1.0f/255.0f);
13591                 }
13592                 else
13593                         alpha = 1.0f/255.0f;
13594
13595                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13596                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13597                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13598                 c4f[ 3] = 1;
13599                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13600                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13601                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13602                 c4f[ 7] = 1;
13603                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13604                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13605                 c4f[10] = decal->color4ub[2][2] * alpha;
13606                 c4f[11] = 1;
13607
13608                 t2f[0] = decal->texcoord2f[0][0];
13609                 t2f[1] = decal->texcoord2f[0][1];
13610                 t2f[2] = decal->texcoord2f[1][0];
13611                 t2f[3] = decal->texcoord2f[1][1];
13612                 t2f[4] = decal->texcoord2f[2][0];
13613                 t2f[5] = decal->texcoord2f[2][1];
13614
13615                 // update vertex positions for animated models
13616                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13617                 {
13618                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13619                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13620                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13621                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13622                 }
13623                 else
13624                 {
13625                         VectorCopy(decal->vertex3f[0], v3f);
13626                         VectorCopy(decal->vertex3f[1], v3f + 3);
13627                         VectorCopy(decal->vertex3f[2], v3f + 6);
13628                 }
13629
13630                 if (r_refdef.fogenabled)
13631                 {
13632                         alpha = RSurf_FogVertex(v3f);
13633                         VectorScale(c4f, alpha, c4f);
13634                         alpha = RSurf_FogVertex(v3f + 3);
13635                         VectorScale(c4f + 4, alpha, c4f + 4);
13636                         alpha = RSurf_FogVertex(v3f + 6);
13637                         VectorScale(c4f + 8, alpha, c4f + 8);
13638                 }
13639
13640                 v3f += 9;
13641                 c4f += 12;
13642                 t2f += 6;
13643                 numtris++;
13644         }
13645
13646         if (numtris > 0)
13647         {
13648                 r_refdef.stats.drawndecals += numtris;
13649
13650                 // now render the decals all at once
13651                 // (this assumes they all use one particle font texture!)
13652                 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);
13653                 R_Mesh_ResetTextureState();
13654                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13655                 GL_DepthMask(false);
13656                 GL_DepthRange(0, 1);
13657                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13658                 GL_DepthTest(true);
13659                 GL_CullFace(GL_NONE);
13660                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13661                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13662                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13663         }
13664 }
13665
13666 static void R_DrawModelDecals(void)
13667 {
13668         int i, numdecals;
13669
13670         // fade faster when there are too many decals
13671         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13672         for (i = 0;i < r_refdef.scene.numentities;i++)
13673                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13674
13675         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13676         for (i = 0;i < r_refdef.scene.numentities;i++)
13677                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13678                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13679
13680         R_DecalSystem_ApplySplatEntitiesQueue();
13681
13682         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13683         for (i = 0;i < r_refdef.scene.numentities;i++)
13684                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13685
13686         r_refdef.stats.totaldecals += numdecals;
13687
13688         if (r_showsurfaces.integer)
13689                 return;
13690
13691         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13692
13693         for (i = 0;i < r_refdef.scene.numentities;i++)
13694         {
13695                 if (!r_refdef.viewcache.entityvisible[i])
13696                         continue;
13697                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13698                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13699         }
13700 }
13701
13702 extern cvar_t mod_collision_bih;
13703 void R_DrawDebugModel(void)
13704 {
13705         entity_render_t *ent = rsurface.entity;
13706         int i, j, k, l, flagsmask;
13707         const msurface_t *surface;
13708         dp_model_t *model = ent->model;
13709         vec3_t v;
13710
13711         switch(vid.renderpath)
13712         {
13713         case RENDERPATH_GL11:
13714         case RENDERPATH_GL13:
13715         case RENDERPATH_GL20:
13716         case RENDERPATH_CGGL:
13717                 break;
13718         case RENDERPATH_D3D9:
13719                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13720                 return;
13721         case RENDERPATH_D3D10:
13722                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13723                 return;
13724         case RENDERPATH_D3D11:
13725                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13726                 return;
13727         }
13728
13729         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13730
13731         R_Mesh_ResetTextureState();
13732         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13733         GL_DepthRange(0, 1);
13734         GL_DepthTest(!r_showdisabledepthtest.integer);
13735         GL_DepthMask(false);
13736         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13737
13738         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13739         {
13740                 int triangleindex;
13741                 int bihleafindex;
13742                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13743                 const q3mbrush_t *brush;
13744                 const bih_t *bih = &model->collision_bih;
13745                 const bih_leaf_t *bihleaf;
13746                 float vertex3f[3][3];
13747                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13748                 cullbox = false;
13749                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13750                 {
13751                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13752                                 continue;
13753                         switch (bihleaf->type)
13754                         {
13755                         case BIH_BRUSH:
13756                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13757                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13758                                 {
13759                                         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);
13760                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13761                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13762                                 }
13763                                 break;
13764                         case BIH_COLLISIONTRIANGLE:
13765                                 triangleindex = bihleaf->itemindex;
13766                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13767                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13768                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13769                                 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);
13770                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13771                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13772                                 break;
13773                         case BIH_RENDERTRIANGLE:
13774                                 triangleindex = bihleaf->itemindex;
13775                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13776                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13777                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13778                                 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);
13779                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13780                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13781                                 break;
13782                         }
13783                 }
13784         }
13785
13786         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13787
13788         if (r_showtris.integer || r_shownormals.integer)
13789         {
13790                 if (r_showdisabledepthtest.integer)
13791                 {
13792                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13793                         GL_DepthMask(false);
13794                 }
13795                 else
13796                 {
13797                         GL_BlendFunc(GL_ONE, GL_ZERO);
13798                         GL_DepthMask(true);
13799                 }
13800                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13801                 {
13802                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13803                                 continue;
13804                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13805                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13806                         {
13807                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13808                                 if (r_showtris.value > 0)
13809                                 {
13810                                         if (!rsurface.texture->currentlayers->depthmask)
13811                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13812                                         else if (ent == r_refdef.scene.worldentity)
13813                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13814                                         else
13815                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13816                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13817                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13818                                         RSurf_DrawBatch();
13819                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13820                                         CHECKGLERROR
13821                                 }
13822                                 if (r_shownormals.value < 0)
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                                 }
13837                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13838                                 {
13839                                         qglBegin(GL_LINES);
13840                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13841                                         {
13842                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13843                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13844                                                 qglVertex3f(v[0], v[1], v[2]);
13845                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13846                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13847                                                 qglVertex3f(v[0], v[1], v[2]);
13848                                         }
13849                                         qglEnd();
13850                                         CHECKGLERROR
13851                                         qglBegin(GL_LINES);
13852                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13853                                         {
13854                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13855                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13856                                                 qglVertex3f(v[0], v[1], v[2]);
13857                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13858                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13859                                                 qglVertex3f(v[0], v[1], v[2]);
13860                                         }
13861                                         qglEnd();
13862                                         CHECKGLERROR
13863                                         qglBegin(GL_LINES);
13864                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13865                                         {
13866                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13867                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13868                                                 qglVertex3f(v[0], v[1], v[2]);
13869                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13870                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13871                                                 qglVertex3f(v[0], v[1], v[2]);
13872                                         }
13873                                         qglEnd();
13874                                         CHECKGLERROR
13875                                 }
13876                         }
13877                 }
13878                 rsurface.texture = NULL;
13879         }
13880 }
13881
13882 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13883 int r_maxsurfacelist = 0;
13884 const msurface_t **r_surfacelist = NULL;
13885 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13886 {
13887         int i, j, endj, flagsmask;
13888         dp_model_t *model = r_refdef.scene.worldmodel;
13889         msurface_t *surfaces;
13890         unsigned char *update;
13891         int numsurfacelist = 0;
13892         if (model == NULL)
13893                 return;
13894
13895         if (r_maxsurfacelist < model->num_surfaces)
13896         {
13897                 r_maxsurfacelist = model->num_surfaces;
13898                 if (r_surfacelist)
13899                         Mem_Free((msurface_t**)r_surfacelist);
13900                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13901         }
13902
13903         RSurf_ActiveWorldEntity();
13904
13905         surfaces = model->data_surfaces;
13906         update = model->brushq1.lightmapupdateflags;
13907
13908         // update light styles on this submodel
13909         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13910         {
13911                 model_brush_lightstyleinfo_t *style;
13912                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13913                 {
13914                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13915                         {
13916                                 int *list = style->surfacelist;
13917                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13918                                 for (j = 0;j < style->numsurfaces;j++)
13919                                         update[list[j]] = true;
13920                         }
13921                 }
13922         }
13923
13924         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13925
13926         if (debug)
13927         {
13928                 R_DrawDebugModel();
13929                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13930                 return;
13931         }
13932
13933         rsurface.lightmaptexture = NULL;
13934         rsurface.deluxemaptexture = NULL;
13935         rsurface.uselightmaptexture = false;
13936         rsurface.texture = NULL;
13937         rsurface.rtlight = NULL;
13938         numsurfacelist = 0;
13939         // add visible surfaces to draw list
13940         for (i = 0;i < model->nummodelsurfaces;i++)
13941         {
13942                 j = model->sortedmodelsurfaces[i];
13943                 if (r_refdef.viewcache.world_surfacevisible[j])
13944                         r_surfacelist[numsurfacelist++] = surfaces + j;
13945         }
13946         // update lightmaps if needed
13947         if (model->brushq1.firstrender)
13948         {
13949                 model->brushq1.firstrender = false;
13950                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13951                         if (update[j])
13952                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13953         }
13954         else if (update)
13955         {
13956                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13957                         if (r_refdef.viewcache.world_surfacevisible[j])
13958                                 if (update[j])
13959                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13960         }
13961         // don't do anything if there were no surfaces
13962         if (!numsurfacelist)
13963         {
13964                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13965                 return;
13966         }
13967         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13968         GL_AlphaTest(false);
13969
13970         // add to stats if desired
13971         if (r_speeds.integer && !skysurfaces && !depthonly)
13972         {
13973                 r_refdef.stats.world_surfaces += numsurfacelist;
13974                 for (j = 0;j < numsurfacelist;j++)
13975                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13976         }
13977
13978         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13979 }
13980
13981 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13982 {
13983         int i, j, endj, flagsmask;
13984         dp_model_t *model = ent->model;
13985         msurface_t *surfaces;
13986         unsigned char *update;
13987         int numsurfacelist = 0;
13988         if (model == NULL)
13989                 return;
13990
13991         if (r_maxsurfacelist < model->num_surfaces)
13992         {
13993                 r_maxsurfacelist = model->num_surfaces;
13994                 if (r_surfacelist)
13995                         Mem_Free((msurface_t **)r_surfacelist);
13996                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13997         }
13998
13999         // if the model is static it doesn't matter what value we give for
14000         // wantnormals and wanttangents, so this logic uses only rules applicable
14001         // to a model, knowing that they are meaningless otherwise
14002         if (ent == r_refdef.scene.worldentity)
14003                 RSurf_ActiveWorldEntity();
14004         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14005                 RSurf_ActiveModelEntity(ent, false, false, false);
14006         else if (prepass)
14007                 RSurf_ActiveModelEntity(ent, true, true, true);
14008         else if (depthonly)
14009         {
14010                 switch (vid.renderpath)
14011                 {
14012                 case RENDERPATH_GL20:
14013                 case RENDERPATH_CGGL:
14014                 case RENDERPATH_D3D9:
14015                 case RENDERPATH_D3D10:
14016                 case RENDERPATH_D3D11:
14017                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14018                         break;
14019                 case RENDERPATH_GL13:
14020                 case RENDERPATH_GL11:
14021                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14022                         break;
14023                 }
14024         }
14025         else
14026         {
14027                 switch (vid.renderpath)
14028                 {
14029                 case RENDERPATH_GL20:
14030                 case RENDERPATH_CGGL:
14031                 case RENDERPATH_D3D9:
14032                 case RENDERPATH_D3D10:
14033                 case RENDERPATH_D3D11:
14034                         RSurf_ActiveModelEntity(ent, true, true, false);
14035                         break;
14036                 case RENDERPATH_GL13:
14037                 case RENDERPATH_GL11:
14038                         RSurf_ActiveModelEntity(ent, true, false, false);
14039                         break;
14040                 }
14041         }
14042
14043         surfaces = model->data_surfaces;
14044         update = model->brushq1.lightmapupdateflags;
14045
14046         // update light styles
14047         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14048         {
14049                 model_brush_lightstyleinfo_t *style;
14050                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14051                 {
14052                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14053                         {
14054                                 int *list = style->surfacelist;
14055                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14056                                 for (j = 0;j < style->numsurfaces;j++)
14057                                         update[list[j]] = true;
14058                         }
14059                 }
14060         }
14061
14062         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14063
14064         if (debug)
14065         {
14066                 R_DrawDebugModel();
14067                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14068                 return;
14069         }
14070
14071         rsurface.lightmaptexture = NULL;
14072         rsurface.deluxemaptexture = NULL;
14073         rsurface.uselightmaptexture = false;
14074         rsurface.texture = NULL;
14075         rsurface.rtlight = NULL;
14076         numsurfacelist = 0;
14077         // add visible surfaces to draw list
14078         for (i = 0;i < model->nummodelsurfaces;i++)
14079                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14080         // don't do anything if there were no surfaces
14081         if (!numsurfacelist)
14082         {
14083                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14084                 return;
14085         }
14086         // update lightmaps if needed
14087         if (update)
14088         {
14089                 int updated = 0;
14090                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14091                 {
14092                         if (update[j])
14093                         {
14094                                 updated++;
14095                                 R_BuildLightMap(ent, surfaces + j);
14096                         }
14097                 }
14098         }
14099         if (update)
14100                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14101                         if (update[j])
14102                                 R_BuildLightMap(ent, surfaces + j);
14103         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14104         GL_AlphaTest(false);
14105
14106         // add to stats if desired
14107         if (r_speeds.integer && !skysurfaces && !depthonly)
14108         {
14109                 r_refdef.stats.entities_surfaces += numsurfacelist;
14110                 for (j = 0;j < numsurfacelist;j++)
14111                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14112         }
14113
14114         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14115 }
14116
14117 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14118 {
14119         static texture_t texture;
14120         static msurface_t surface;
14121         const msurface_t *surfacelist = &surface;
14122
14123         // fake enough texture and surface state to render this geometry
14124
14125         texture.update_lastrenderframe = -1; // regenerate this texture
14126         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14127         texture.currentskinframe = skinframe;
14128         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14129         texture.offsetmapping = OFFSETMAPPING_OFF;
14130         texture.offsetscale = 1;
14131         texture.specularscalemod = 1;
14132         texture.specularpowermod = 1;
14133
14134         surface.texture = &texture;
14135         surface.num_triangles = numtriangles;
14136         surface.num_firsttriangle = firsttriangle;
14137         surface.num_vertices = numvertices;
14138         surface.num_firstvertex = firstvertex;
14139
14140         // now render it
14141         rsurface.texture = R_GetCurrentTexture(surface.texture);
14142         rsurface.lightmaptexture = NULL;
14143         rsurface.deluxemaptexture = NULL;
14144         rsurface.uselightmaptexture = false;
14145         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14146 }
14147
14148 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)
14149 {
14150         static msurface_t surface;
14151         const msurface_t *surfacelist = &surface;
14152
14153         // fake enough texture and surface state to render this geometry
14154
14155         surface.texture = texture;
14156         surface.num_triangles = numtriangles;
14157         surface.num_firsttriangle = firsttriangle;
14158         surface.num_vertices = numvertices;
14159         surface.num_firstvertex = firstvertex;
14160
14161         // now render it
14162         rsurface.texture = R_GetCurrentTexture(surface.texture);
14163         rsurface.lightmaptexture = NULL;
14164         rsurface.deluxemaptexture = NULL;
14165         rsurface.uselightmaptexture = false;
14166         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14167 }