]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
Fix a possible crash when an invalid skinframe gets accessed after cl.time steps...
[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                         mode = SHADERMODE_WATER;
5219                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5220                         mode = SHADERMODE_REFRACTION;
5221                 else
5222                 {
5223                         mode = SHADERMODE_GENERIC;
5224                         permutation |= SHADERPERMUTATION_DIFFUSE;
5225                 }
5226                 GL_AlphaTest(false);
5227                 GL_BlendFunc(GL_ONE, GL_ZERO);
5228                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5229         }
5230         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5231         {
5232                 if (r_glsl_offsetmapping.integer)
5233                 {
5234                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5235                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5236                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5237                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5238                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5239                         {
5240                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5241                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5242                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5243                         }
5244                 }
5245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5248                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5249                 // normalmap (deferred prepass), may use alpha test on diffuse
5250                 mode = SHADERMODE_DEFERREDGEOMETRY;
5251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5252                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5253                 GL_AlphaTest(false);
5254                 GL_BlendFunc(GL_ONE, GL_ZERO);
5255                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5256         }
5257         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5258         {
5259                 if (r_glsl_offsetmapping.integer)
5260                 {
5261                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5262                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5263                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5264                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5265                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5266                         {
5267                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5268                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5269                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5270                         }
5271                 }
5272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5273                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5274                 // light source
5275                 mode = SHADERMODE_LIGHTSOURCE;
5276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5277                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5278                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5279                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5280                 if (diffusescale > 0)
5281                         permutation |= SHADERPERMUTATION_DIFFUSE;
5282                 if (specularscale > 0)
5283                 {
5284                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5285                         if (r_shadow_glossexact.integer)
5286                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5287                 }
5288                 if (r_refdef.fogenabled)
5289                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5290                 if (rsurface.texture->colormapping)
5291                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5292                 if (r_shadow_usingshadowmap2d)
5293                 {
5294                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5295                         if(r_shadow_shadowmapvsdct)
5296                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5297
5298                         if (r_shadow_shadowmapsampler)
5299                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5300                         if (r_shadow_shadowmappcf > 1)
5301                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5302                         else if (r_shadow_shadowmappcf)
5303                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5304                 }
5305                 if (rsurface.texture->reflectmasktexture)
5306                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5307                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5308                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5309                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5310         }
5311         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5312         {
5313                 if (r_glsl_offsetmapping.integer)
5314                 {
5315                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5316                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5317                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5318                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5319                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5320                         {
5321                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5322                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5323                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5324                         }
5325                 }
5326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5328                 // unshaded geometry (fullbright or ambient model lighting)
5329                 mode = SHADERMODE_FLATCOLOR;
5330                 ambientscale = diffusescale = specularscale = 0;
5331                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5332                         permutation |= SHADERPERMUTATION_GLOW;
5333                 if (r_refdef.fogenabled)
5334                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5335                 if (rsurface.texture->colormapping)
5336                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5337                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5338                 {
5339                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5340                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5341
5342                         if (r_shadow_shadowmapsampler)
5343                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5344                         if (r_shadow_shadowmappcf > 1)
5345                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5346                         else if (r_shadow_shadowmappcf)
5347                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5348                 }
5349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5350                         permutation |= SHADERPERMUTATION_REFLECTION;
5351                 if (rsurface.texture->reflectmasktexture)
5352                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5353                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5354                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5355                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5356         }
5357         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5358         {
5359                 if (r_glsl_offsetmapping.integer)
5360                 {
5361                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5362                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5363                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5364                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5365                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5366                         {
5367                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5368                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5369                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5370                         }
5371                 }
5372                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5373                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5374                 // directional model lighting
5375                 mode = SHADERMODE_LIGHTDIRECTION;
5376                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5377                         permutation |= SHADERPERMUTATION_GLOW;
5378                 permutation |= SHADERPERMUTATION_DIFFUSE;
5379                 if (specularscale > 0)
5380                 {
5381                         permutation |= SHADERPERMUTATION_SPECULAR;
5382                         if (r_shadow_glossexact.integer)
5383                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5384                 }
5385                 if (r_refdef.fogenabled)
5386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5387                 if (rsurface.texture->colormapping)
5388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5389                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5390                 {
5391                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5392                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5393
5394                         if (r_shadow_shadowmapsampler)
5395                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5396                         if (r_shadow_shadowmappcf > 1)
5397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5398                         else if (r_shadow_shadowmappcf)
5399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5400                 }
5401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5402                         permutation |= SHADERPERMUTATION_REFLECTION;
5403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5405                 if (rsurface.texture->reflectmasktexture)
5406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5407                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5408                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5409                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5410         }
5411         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5412         {
5413                 if (r_glsl_offsetmapping.integer)
5414                 {
5415                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5416                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5417                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5419                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5420                         {
5421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5422                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5423                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5424                         }
5425                 }
5426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5428                 // ambient model lighting
5429                 mode = SHADERMODE_LIGHTDIRECTION;
5430                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5431                         permutation |= SHADERPERMUTATION_GLOW;
5432                 if (r_refdef.fogenabled)
5433                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5434                 if (rsurface.texture->colormapping)
5435                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5436                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5437                 {
5438                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5439                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5440
5441                         if (r_shadow_shadowmapsampler)
5442                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5443                         if (r_shadow_shadowmappcf > 1)
5444                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5445                         else if (r_shadow_shadowmappcf)
5446                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5447                 }
5448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5449                         permutation |= SHADERPERMUTATION_REFLECTION;
5450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5452                 if (rsurface.texture->reflectmasktexture)
5453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5454                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5455                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5456                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5457         }
5458         else
5459         {
5460                 if (r_glsl_offsetmapping.integer)
5461                 {
5462                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5467                         {
5468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5470                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5471                         }
5472                 }
5473                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5475                 // lightmapped wall
5476                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5477                         permutation |= SHADERPERMUTATION_GLOW;
5478                 if (r_refdef.fogenabled)
5479                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5480                 if (rsurface.texture->colormapping)
5481                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5482                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5483                 {
5484                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5485                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5486
5487                         if (r_shadow_shadowmapsampler)
5488                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5489                         if (r_shadow_shadowmappcf > 1)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5491                         else if (r_shadow_shadowmappcf)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5493                 }
5494                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5495                         permutation |= SHADERPERMUTATION_REFLECTION;
5496                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5497                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5498                 if (rsurface.texture->reflectmasktexture)
5499                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5500                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5501                 {
5502                         // deluxemapping (light direction texture)
5503                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5504                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5505                         else
5506                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5507                         permutation |= SHADERPERMUTATION_DIFFUSE;
5508                         if (specularscale > 0)
5509                         {
5510                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5511                                 if (r_shadow_glossexact.integer)
5512                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5513                         }
5514                 }
5515                 else if (r_glsl_deluxemapping.integer >= 2)
5516                 {
5517                         // fake deluxemapping (uniform light direction in tangentspace)
5518                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5519                         permutation |= SHADERPERMUTATION_DIFFUSE;
5520                         if (specularscale > 0)
5521                         {
5522                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5523                                 if (r_shadow_glossexact.integer)
5524                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5525                         }
5526                 }
5527                 else if (rsurface.uselightmaptexture)
5528                 {
5529                         // ordinary lightmapping (q1bsp, q3bsp)
5530                         mode = SHADERMODE_LIGHTMAP;
5531                 }
5532                 else
5533                 {
5534                         // ordinary vertex coloring (q3bsp)
5535                         mode = SHADERMODE_VERTEXCOLOR;
5536                 }
5537                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5538                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5539                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5540         }
5541         if(!allow_colormod)
5542                 colormod = dummy_colormod;
5543         switch(vid.renderpath)
5544         {
5545         case RENDERPATH_D3D9:
5546 #ifdef SUPPORTD3D
5547                 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);
5548                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5549                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5550                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5551                 if (mode == SHADERMODE_LIGHTSOURCE)
5552                 {
5553                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5554                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5555                 }
5556                 else
5557                 {
5558                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5559                         {
5560                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5561                         }
5562                 }
5563                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5564                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5565                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5566                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5567                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5568
5569                 if (mode == SHADERMODE_LIGHTSOURCE)
5570                 {
5571                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5572                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5573                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5574                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5575                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5576
5577                         // additive passes are only darkened by fog, not tinted
5578                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5580                 }
5581                 else
5582                 {
5583                         if (mode == SHADERMODE_FLATCOLOR)
5584                         {
5585                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5586                         }
5587                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5588                         {
5589                                 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]);
5590                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5591                                 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);
5592                                 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);
5593                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5594                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5595                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5596                         }
5597                         else
5598                         {
5599                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5600                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5601                                 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);
5602                                 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);
5603                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5604                         }
5605                         // additive passes are only darkened by fog, not tinted
5606                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5607                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5608                         else
5609                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5610                         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);
5611                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5612                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5613                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5614                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5615                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5616                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5617                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5618                 }
5619                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5620                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5621                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5622                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5623                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5624                 if (rsurface.texture->pantstexture)
5625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5626                 else
5627                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5628                 if (rsurface.texture->shirttexture)
5629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5630                 else
5631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5632                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5633                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5634                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5635                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5636                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5637                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5638                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5639
5640                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5641                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5642                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5643                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5648                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5649                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5650                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5651                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5652                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5653                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5654                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5655                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5656                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5657                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5658                 {
5659                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5660                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5661                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5662                 }
5663                 else
5664                 {
5665                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5666                 }
5667 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5668 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5669                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5671                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5672                 {
5673                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5674                         if (rsurface.rtlight)
5675                         {
5676                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5677                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5678                         }
5679                 }
5680 #endif
5681                 break;
5682         case RENDERPATH_D3D10:
5683                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5684                 break;
5685         case RENDERPATH_D3D11:
5686                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5687                 break;
5688         case RENDERPATH_GL20:
5689                 if (gl_mesh_separatearrays.integer)
5690                 {
5691                         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);
5692                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5693                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5694                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5695                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5696                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5697                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5698                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5699                 }
5700                 else
5701                 {
5702                         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);
5703                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5704                 }
5705                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5706                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5707                 if (mode == SHADERMODE_LIGHTSOURCE)
5708                 {
5709                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5710                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5711                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5712                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5713                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5714                         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);
5715         
5716                         // additive passes are only darkened by fog, not tinted
5717                         if (r_glsl_permutation->loc_FogColor >= 0)
5718                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5719                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5720                 }
5721                 else
5722                 {
5723                         if (mode == SHADERMODE_FLATCOLOR)
5724                         {
5725                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5726                         }
5727                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5728                         {
5729                                 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]);
5730                                 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]);
5731                                 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);
5732                                 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);
5733                                 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);
5734                                 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]);
5735                                 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]);
5736                         }
5737                         else
5738                         {
5739                                 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]);
5740                                 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]);
5741                                 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);
5742                                 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);
5743                                 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);
5744                         }
5745                         // additive passes are only darkened by fog, not tinted
5746                         if (r_glsl_permutation->loc_FogColor >= 0)
5747                         {
5748                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5749                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5750                                 else
5751                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5752                         }
5753                         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);
5754                         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]);
5755                         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]);
5756                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5757                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5758                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5759                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5760                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5761                 }
5762                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5763                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5764                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5765                 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]);
5766                 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]);
5767
5768                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5769                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5770                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5771                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5772                 {
5773                         if (rsurface.texture->pantstexture)
5774                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5775                         else
5776                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5777                 }
5778                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5779                 {
5780                         if (rsurface.texture->shirttexture)
5781                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5782                         else
5783                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5784                 }
5785                 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]);
5786                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5787                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5788                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5789                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5790                 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]);
5791                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5792
5793         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5794         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5795         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5796                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5797                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5798                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5799                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5800                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5801                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5802                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5803                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5804                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5805                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5806                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5807                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5808                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5809                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5810                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5811                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5812                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5813                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5814                 {
5815                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5816                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5817                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5818                 }
5819                 else
5820                 {
5821                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5822                 }
5823 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5824 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5825                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5826                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5827                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5828                 {
5829                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5830                         if (rsurface.rtlight)
5831                         {
5832                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5833                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5834                         }
5835                 }
5836                 CHECKGLERROR
5837                 break;
5838         case RENDERPATH_CGGL:
5839 #ifdef SUPPORTCG
5840                 if (gl_mesh_separatearrays.integer)
5841                 {
5842                         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);
5843                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5850                 }
5851                 else
5852                 {
5853                         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);
5854                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5855                 }
5856                 R_SetupShader_SetPermutationCG(mode, permutation);
5857                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5858                 if (mode == SHADERMODE_LIGHTSOURCE)
5859                 {
5860                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5861                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5862                 }
5863                 else
5864                 {
5865                         if (mode == SHADERMODE_LIGHTDIRECTION)
5866                         {
5867                                 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
5868                         }
5869                 }
5870                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5871                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5872                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5873                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5874                 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
5875                 CHECKGLERROR
5876
5877                 if (mode == SHADERMODE_LIGHTSOURCE)
5878                 {
5879                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5880                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5881                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5882                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5883                         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
5884
5885                         // additive passes are only darkened by fog, not tinted
5886                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5887                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5888                 }
5889                 else
5890                 {
5891                         if (mode == SHADERMODE_FLATCOLOR)
5892                         {
5893                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5894                         }
5895                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5896                         {
5897                                 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
5898                                 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
5899                                 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
5900                                 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
5901                                 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
5902                                 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
5903                                 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
5904                         }
5905                         else
5906                         {
5907                                 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
5908                                 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
5909                                 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
5910                                 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
5911                                 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
5912                         }
5913                         // additive passes are only darkened by fog, not tinted
5914                         if (r_cg_permutation->fp_FogColor)
5915                         {
5916                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5917                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5918                                 else
5919                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5920                                 CHECKCGERROR
5921                         }
5922                         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
5923                         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
5924                         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
5925                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5926                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5927                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5928                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5929                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5930                 }
5931                 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
5932                 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
5933                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5934                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5935                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5936                 if (r_cg_permutation->fp_Color_Pants)
5937                 {
5938                         if (rsurface.texture->pantstexture)
5939                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5940                         else
5941                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5942                         CHECKCGERROR
5943                 }
5944                 if (r_cg_permutation->fp_Color_Shirt)
5945                 {
5946                         if (rsurface.texture->shirttexture)
5947                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5948                         else
5949                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5950                         CHECKCGERROR
5951                 }
5952                 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
5953                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5954                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5955                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5956                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5957                 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
5958                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5959
5960         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5961         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5962         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5963                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5964                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5965                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5966                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5967                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5968                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5969                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5970                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5971                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5972                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5973                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5974                 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
5975                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5976                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5977                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5978                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5979                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5980                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5981                 {
5982                         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
5983                         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
5984                         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
5985                 }
5986                 else
5987                 {
5988                         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
5989                 }
5990                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5991                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5992                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5993                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5994                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5995                 {
5996                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5997                         if (rsurface.rtlight)
5998                         {
5999                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6000                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6001                         }
6002                 }
6003
6004                 CHECKGLERROR
6005 #endif
6006                 break;
6007         case RENDERPATH_GL13:
6008         case RENDERPATH_GL11:
6009                 break;
6010         }
6011 }
6012
6013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6014 {
6015         // select a permutation of the lighting shader appropriate to this
6016         // combination of texture, entity, light source, and fogging, only use the
6017         // minimum features necessary to avoid wasting rendering time in the
6018         // fragment shader on features that are not being used
6019         unsigned int permutation = 0;
6020         unsigned int mode = 0;
6021         const float *lightcolorbase = rtlight->currentcolor;
6022         float ambientscale = rtlight->ambientscale;
6023         float diffusescale = rtlight->diffusescale;
6024         float specularscale = rtlight->specularscale;
6025         // this is the location of the light in view space
6026         vec3_t viewlightorigin;
6027         // this transforms from view space (camera) to light space (cubemap)
6028         matrix4x4_t viewtolight;
6029         matrix4x4_t lighttoview;
6030         float viewtolight16f[16];
6031         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6032         // light source
6033         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6034         if (rtlight->currentcubemap != r_texture_whitecube)
6035                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6036         if (diffusescale > 0)
6037                 permutation |= SHADERPERMUTATION_DIFFUSE;
6038         if (specularscale > 0)
6039         {
6040                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6041                 if (r_shadow_glossexact.integer)
6042                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6043         }
6044         if (r_shadow_usingshadowmap2d)
6045         {
6046                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6047                 if (r_shadow_shadowmapvsdct)
6048                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6049
6050                 if (r_shadow_shadowmapsampler)
6051                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6052                 if (r_shadow_shadowmappcf > 1)
6053                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6054                 else if (r_shadow_shadowmappcf)
6055                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6056         }
6057         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6058         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6059         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6060         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6061         switch(vid.renderpath)
6062         {
6063         case RENDERPATH_D3D9:
6064 #ifdef SUPPORTD3D
6065                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6066                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6067                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6068                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6069                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6070                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6071                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6072                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6073                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6074                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6075                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6076
6077                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6078                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6079                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6080                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6081                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6082                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6083 #endif
6084                 break;
6085         case RENDERPATH_D3D10:
6086                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6087                 break;
6088         case RENDERPATH_D3D11:
6089                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6090                 break;
6091         case RENDERPATH_GL20:
6092                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6093                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6094                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6095                 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);
6096                 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);
6097                 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);
6098                 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]);
6099                 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]);
6100                 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));
6101                 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]);
6102                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6103
6104                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6105                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6106                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6107                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6108                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6109                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6110                 break;
6111         case RENDERPATH_CGGL:
6112 #ifdef SUPPORTCG
6113                 R_SetupShader_SetPermutationCG(mode, permutation);
6114                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6115                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6116                 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
6117                 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
6118                 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
6119                 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
6120                 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
6121                 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
6122                 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
6123                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6124
6125                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6126                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6127                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6128                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6129                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6130                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6131 #endif
6132                 break;
6133         case RENDERPATH_GL13:
6134         case RENDERPATH_GL11:
6135                 break;
6136         }
6137 }
6138
6139 #define SKINFRAME_HASH 1024
6140
6141 typedef struct
6142 {
6143         int loadsequence; // incremented each level change
6144         memexpandablearray_t array;
6145         skinframe_t *hash[SKINFRAME_HASH];
6146 }
6147 r_skinframe_t;
6148 r_skinframe_t r_skinframe;
6149
6150 void R_SkinFrame_PrepareForPurge(void)
6151 {
6152         r_skinframe.loadsequence++;
6153         // wrap it without hitting zero
6154         if (r_skinframe.loadsequence >= 200)
6155                 r_skinframe.loadsequence = 1;
6156 }
6157
6158 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6159 {
6160         if (!skinframe)
6161                 return;
6162         // mark the skinframe as used for the purging code
6163         skinframe->loadsequence = r_skinframe.loadsequence;
6164 }
6165
6166 void R_SkinFrame_Purge(void)
6167 {
6168         int i;
6169         skinframe_t *s;
6170         for (i = 0;i < SKINFRAME_HASH;i++)
6171         {
6172                 for (s = r_skinframe.hash[i];s;s = s->next)
6173                 {
6174                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6175                         {
6176                                 if (s->merged == s->base)
6177                                         s->merged = NULL;
6178                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6179                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6180                                 R_PurgeTexture(s->merged);s->merged = NULL;
6181                                 R_PurgeTexture(s->base  );s->base   = NULL;
6182                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6183                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6184                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6185                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6186                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6187                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6188                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6189                                 s->loadsequence = 0;
6190                         }
6191                 }
6192         }
6193 }
6194
6195 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6196         skinframe_t *item;
6197         char basename[MAX_QPATH];
6198
6199         Image_StripImageExtension(name, basename, sizeof(basename));
6200
6201         if( last == NULL ) {
6202                 int hashindex;
6203                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6204                 item = r_skinframe.hash[hashindex];
6205         } else {
6206                 item = last->next;
6207         }
6208
6209         // linearly search through the hash bucket
6210         for( ; item ; item = item->next ) {
6211                 if( !strcmp( item->basename, basename ) ) {
6212                         return item;
6213                 }
6214         }
6215         return NULL;
6216 }
6217
6218 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6219 {
6220         skinframe_t *item;
6221         int hashindex;
6222         char basename[MAX_QPATH];
6223
6224         Image_StripImageExtension(name, basename, sizeof(basename));
6225
6226         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6227         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6228                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6229                         break;
6230
6231         if (!item) {
6232                 rtexture_t *dyntexture;
6233                 // check whether its a dynamic texture
6234                 dyntexture = CL_GetDynTexture( basename );
6235                 if (!add && !dyntexture)
6236                         return NULL;
6237                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6238                 memset(item, 0, sizeof(*item));
6239                 strlcpy(item->basename, basename, sizeof(item->basename));
6240                 item->base = dyntexture; // either NULL or dyntexture handle
6241                 item->textureflags = textureflags;
6242                 item->comparewidth = comparewidth;
6243                 item->compareheight = compareheight;
6244                 item->comparecrc = comparecrc;
6245                 item->next = r_skinframe.hash[hashindex];
6246                 r_skinframe.hash[hashindex] = item;
6247         }
6248         else if( item->base == NULL )
6249         {
6250                 rtexture_t *dyntexture;
6251                 // check whether its a dynamic texture
6252                 // 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]
6253                 dyntexture = CL_GetDynTexture( basename );
6254                 item->base = dyntexture; // either NULL or dyntexture handle
6255         }
6256
6257         R_SkinFrame_MarkUsed(item);
6258         return item;
6259 }
6260
6261 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6262         { \
6263                 unsigned long long avgcolor[5], wsum; \
6264                 int pix, comp, w; \
6265                 avgcolor[0] = 0; \
6266                 avgcolor[1] = 0; \
6267                 avgcolor[2] = 0; \
6268                 avgcolor[3] = 0; \
6269                 avgcolor[4] = 0; \
6270                 wsum = 0; \
6271                 for(pix = 0; pix < cnt; ++pix) \
6272                 { \
6273                         w = 0; \
6274                         for(comp = 0; comp < 3; ++comp) \
6275                                 w += getpixel; \
6276                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6277                         { \
6278                                 ++wsum; \
6279                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6280                                 w = getpixel; \
6281                                 for(comp = 0; comp < 3; ++comp) \
6282                                         avgcolor[comp] += getpixel * w; \
6283                                 avgcolor[3] += w; \
6284                         } \
6285                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6286                         avgcolor[4] += getpixel; \
6287                 } \
6288                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6289                         avgcolor[3] = 1; \
6290                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6291                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6292                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6293                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6294         }
6295
6296 extern cvar_t gl_picmip;
6297 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6298 {
6299         int j;
6300         unsigned char *pixels;
6301         unsigned char *bumppixels;
6302         unsigned char *basepixels = NULL;
6303         int basepixels_width = 0;
6304         int basepixels_height = 0;
6305         skinframe_t *skinframe;
6306         rtexture_t *ddsbase = NULL;
6307         qboolean ddshasalpha = false;
6308         float ddsavgcolor[4];
6309         char basename[MAX_QPATH];
6310         int miplevel = R_PicmipForFlags(textureflags);
6311         int savemiplevel = miplevel;
6312         int mymiplevel;
6313
6314         if (cls.state == ca_dedicated)
6315                 return NULL;
6316
6317         // return an existing skinframe if already loaded
6318         // if loading of the first image fails, don't make a new skinframe as it
6319         // would cause all future lookups of this to be missing
6320         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6321         if (skinframe && skinframe->base)
6322                 return skinframe;
6323
6324         Image_StripImageExtension(name, basename, sizeof(basename));
6325
6326         // check for DDS texture file first
6327         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6328         {
6329                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6330                 if (basepixels == NULL)
6331                         return NULL;
6332         }
6333
6334         // FIXME handle miplevel
6335
6336         if (developer_loading.integer)
6337                 Con_Printf("loading skin \"%s\"\n", name);
6338
6339         // we've got some pixels to store, so really allocate this new texture now
6340         if (!skinframe)
6341                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6342         skinframe->stain = NULL;
6343         skinframe->merged = NULL;
6344         skinframe->base = NULL;
6345         skinframe->pants = NULL;
6346         skinframe->shirt = NULL;
6347         skinframe->nmap = NULL;
6348         skinframe->gloss = NULL;
6349         skinframe->glow = NULL;
6350         skinframe->fog = NULL;
6351         skinframe->reflect = NULL;
6352         skinframe->hasalpha = false;
6353
6354         if (ddsbase)
6355         {
6356                 skinframe->base = ddsbase;
6357                 skinframe->hasalpha = ddshasalpha;
6358                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6359                 if (r_loadfog && skinframe->hasalpha)
6360                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6361                 //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]);
6362         }
6363         else
6364         {
6365                 basepixels_width = image_width;
6366                 basepixels_height = image_height;
6367                 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);
6368                 if (textureflags & TEXF_ALPHA)
6369                 {
6370                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6371                         {
6372                                 if (basepixels[j] < 255)
6373                                 {
6374                                         skinframe->hasalpha = true;
6375                                         break;
6376                                 }
6377                         }
6378                         if (r_loadfog && skinframe->hasalpha)
6379                         {
6380                                 // has transparent pixels
6381                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6382                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6383                                 {
6384                                         pixels[j+0] = 255;
6385                                         pixels[j+1] = 255;
6386                                         pixels[j+2] = 255;
6387                                         pixels[j+3] = basepixels[j+3];
6388                                 }
6389                                 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);
6390                                 Mem_Free(pixels);
6391                         }
6392                 }
6393                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6394                 //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]);
6395                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6396                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6398                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6399         }
6400
6401         if (r_loaddds)
6402         {
6403                 mymiplevel = savemiplevel;
6404                 if (r_loadnormalmap)
6405                         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);
6406                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6407                 if (r_loadgloss)
6408                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6409                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6410                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6411                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6412         }
6413
6414         // _norm is the name used by tenebrae and has been adopted as standard
6415         if (r_loadnormalmap && skinframe->nmap == NULL)
6416         {
6417                 mymiplevel = savemiplevel;
6418                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6419                 {
6420                         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);
6421                         Mem_Free(pixels);
6422                         pixels = NULL;
6423                 }
6424                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6425                 {
6426                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6427                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
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                         Mem_Free(bumppixels);
6431                 }
6432                 else if (r_shadow_bumpscale_basetexture.value > 0)
6433                 {
6434                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6435                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6436                         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);
6437                         Mem_Free(pixels);
6438                 }
6439                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6440                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6441         }
6442
6443         // _luma is supported only for tenebrae compatibility
6444         // _glow is the preferred name
6445         mymiplevel = savemiplevel;
6446         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))))
6447         {
6448                 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);
6449                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6450                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6451                 Mem_Free(pixels);pixels = NULL;
6452         }
6453
6454         mymiplevel = savemiplevel;
6455         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6456         {
6457                 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);
6458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6459                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6460                 Mem_Free(pixels);
6461                 pixels = NULL;
6462         }
6463
6464         mymiplevel = savemiplevel;
6465         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6466         {
6467                 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);
6468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6469                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6470                 Mem_Free(pixels);
6471                 pixels = NULL;
6472         }
6473
6474         mymiplevel = savemiplevel;
6475         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6476         {
6477                 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);
6478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6479                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6480                 Mem_Free(pixels);
6481                 pixels = NULL;
6482         }
6483
6484         mymiplevel = savemiplevel;
6485         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6486         {
6487                 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);
6488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6489                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6490                 Mem_Free(pixels);
6491                 pixels = NULL;
6492         }
6493
6494         if (basepixels)
6495                 Mem_Free(basepixels);
6496
6497         return skinframe;
6498 }
6499
6500 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6501 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6502 {
6503         int i;
6504         unsigned char *temp1, *temp2;
6505         skinframe_t *skinframe;
6506
6507         if (cls.state == ca_dedicated)
6508                 return NULL;
6509
6510         // if already loaded just return it, otherwise make a new skinframe
6511         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6512         if (skinframe && skinframe->base)
6513                 return skinframe;
6514
6515         skinframe->stain = NULL;
6516         skinframe->merged = NULL;
6517         skinframe->base = NULL;
6518         skinframe->pants = NULL;
6519         skinframe->shirt = NULL;
6520         skinframe->nmap = NULL;
6521         skinframe->gloss = NULL;
6522         skinframe->glow = NULL;
6523         skinframe->fog = NULL;
6524         skinframe->reflect = NULL;
6525         skinframe->hasalpha = false;
6526
6527         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6528         if (!skindata)
6529                 return NULL;
6530
6531         if (developer_loading.integer)
6532                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6533
6534         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6535         {
6536                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6537                 temp2 = temp1 + width * height * 4;
6538                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6539                 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);
6540                 Mem_Free(temp1);
6541         }
6542         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6543         if (textureflags & TEXF_ALPHA)
6544         {
6545                 for (i = 3;i < width * height * 4;i += 4)
6546                 {
6547                         if (skindata[i] < 255)
6548                         {
6549                                 skinframe->hasalpha = true;
6550                                 break;
6551                         }
6552                 }
6553                 if (r_loadfog && skinframe->hasalpha)
6554                 {
6555                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6556                         memcpy(fogpixels, skindata, width * height * 4);
6557                         for (i = 0;i < width * height * 4;i += 4)
6558                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6559                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6560                         Mem_Free(fogpixels);
6561                 }
6562         }
6563
6564         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6565         //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]);
6566
6567         return skinframe;
6568 }
6569
6570 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6571 {
6572         int i;
6573         int featuresmask;
6574         skinframe_t *skinframe;
6575
6576         if (cls.state == ca_dedicated)
6577                 return NULL;
6578
6579         // if already loaded just return it, otherwise make a new skinframe
6580         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6581         if (skinframe && skinframe->base)
6582                 return skinframe;
6583
6584         skinframe->stain = NULL;
6585         skinframe->merged = NULL;
6586         skinframe->base = NULL;
6587         skinframe->pants = NULL;
6588         skinframe->shirt = NULL;
6589         skinframe->nmap = NULL;
6590         skinframe->gloss = NULL;
6591         skinframe->glow = NULL;
6592         skinframe->fog = NULL;
6593         skinframe->reflect = NULL;
6594         skinframe->hasalpha = false;
6595
6596         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6597         if (!skindata)
6598                 return NULL;
6599
6600         if (developer_loading.integer)
6601                 Con_Printf("loading quake skin \"%s\"\n", name);
6602
6603         // 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)
6604         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6605         memcpy(skinframe->qpixels, skindata, width*height);
6606         skinframe->qwidth = width;
6607         skinframe->qheight = height;
6608
6609         featuresmask = 0;
6610         for (i = 0;i < width * height;i++)
6611                 featuresmask |= palette_featureflags[skindata[i]];
6612
6613         skinframe->hasalpha = false;
6614         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6615         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6616         skinframe->qgeneratemerged = true;
6617         skinframe->qgeneratebase = skinframe->qhascolormapping;
6618         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6619
6620         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6621         //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]);
6622
6623         return skinframe;
6624 }
6625
6626 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6627 {
6628         int width;
6629         int height;
6630         unsigned char *skindata;
6631
6632         if (!skinframe->qpixels)
6633                 return;
6634
6635         if (!skinframe->qhascolormapping)
6636                 colormapped = false;
6637
6638         if (colormapped)
6639         {
6640                 if (!skinframe->qgeneratebase)
6641                         return;
6642         }
6643         else
6644         {
6645                 if (!skinframe->qgeneratemerged)
6646                         return;
6647         }
6648
6649         width = skinframe->qwidth;
6650         height = skinframe->qheight;
6651         skindata = skinframe->qpixels;
6652
6653         if (skinframe->qgeneratenmap)
6654         {
6655                 unsigned char *temp1, *temp2;
6656                 skinframe->qgeneratenmap = false;
6657                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6658                 temp2 = temp1 + width * height * 4;
6659                 // use either a custom palette or the quake palette
6660                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6661                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6662                 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);
6663                 Mem_Free(temp1);
6664         }
6665
6666         if (skinframe->qgenerateglow)
6667         {
6668                 skinframe->qgenerateglow = false;
6669                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6670         }
6671
6672         if (colormapped)
6673         {
6674                 skinframe->qgeneratebase = false;
6675                 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);
6676                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6677                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6678         }
6679         else
6680         {
6681                 skinframe->qgeneratemerged = false;
6682                 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);
6683         }
6684
6685         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6686         {
6687                 Mem_Free(skinframe->qpixels);
6688                 skinframe->qpixels = NULL;
6689         }
6690 }
6691
6692 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)
6693 {
6694         int i;
6695         skinframe_t *skinframe;
6696
6697         if (cls.state == ca_dedicated)
6698                 return NULL;
6699
6700         // if already loaded just return it, otherwise make a new skinframe
6701         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6702         if (skinframe && skinframe->base)
6703                 return skinframe;
6704
6705         skinframe->stain = NULL;
6706         skinframe->merged = NULL;
6707         skinframe->base = NULL;
6708         skinframe->pants = NULL;
6709         skinframe->shirt = NULL;
6710         skinframe->nmap = NULL;
6711         skinframe->gloss = NULL;
6712         skinframe->glow = NULL;
6713         skinframe->fog = NULL;
6714         skinframe->reflect = NULL;
6715         skinframe->hasalpha = false;
6716
6717         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6718         if (!skindata)
6719                 return NULL;
6720
6721         if (developer_loading.integer)
6722                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6723
6724         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6725         if (textureflags & TEXF_ALPHA)
6726         {
6727                 for (i = 0;i < width * height;i++)
6728                 {
6729                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6730                         {
6731                                 skinframe->hasalpha = true;
6732                                 break;
6733                         }
6734                 }
6735                 if (r_loadfog && skinframe->hasalpha)
6736                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6737         }
6738
6739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6740         //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]);
6741
6742         return skinframe;
6743 }
6744
6745 skinframe_t *R_SkinFrame_LoadMissing(void)
6746 {
6747         skinframe_t *skinframe;
6748
6749         if (cls.state == ca_dedicated)
6750                 return NULL;
6751
6752         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6753         skinframe->stain = NULL;
6754         skinframe->merged = NULL;
6755         skinframe->base = NULL;
6756         skinframe->pants = NULL;
6757         skinframe->shirt = NULL;
6758         skinframe->nmap = NULL;
6759         skinframe->gloss = NULL;
6760         skinframe->glow = NULL;
6761         skinframe->fog = NULL;
6762         skinframe->reflect = NULL;
6763         skinframe->hasalpha = false;
6764
6765         skinframe->avgcolor[0] = rand() / RAND_MAX;
6766         skinframe->avgcolor[1] = rand() / RAND_MAX;
6767         skinframe->avgcolor[2] = rand() / RAND_MAX;
6768         skinframe->avgcolor[3] = 1;
6769
6770         return skinframe;
6771 }
6772
6773 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6774 typedef struct suffixinfo_s
6775 {
6776         const char *suffix;
6777         qboolean flipx, flipy, flipdiagonal;
6778 }
6779 suffixinfo_t;
6780 static suffixinfo_t suffix[3][6] =
6781 {
6782         {
6783                 {"px",   false, false, false},
6784                 {"nx",   false, false, false},
6785                 {"py",   false, false, false},
6786                 {"ny",   false, false, false},
6787                 {"pz",   false, false, false},
6788                 {"nz",   false, false, false}
6789         },
6790         {
6791                 {"posx", false, false, false},
6792                 {"negx", false, false, false},
6793                 {"posy", false, false, false},
6794                 {"negy", false, false, false},
6795                 {"posz", false, false, false},
6796                 {"negz", false, false, false}
6797         },
6798         {
6799                 {"rt",    true, false,  true},
6800                 {"lf",   false,  true,  true},
6801                 {"ft",    true,  true, false},
6802                 {"bk",   false, false, false},
6803                 {"up",    true, false,  true},
6804                 {"dn",    true, false,  true}
6805         }
6806 };
6807
6808 static int componentorder[4] = {0, 1, 2, 3};
6809
6810 rtexture_t *R_LoadCubemap(const char *basename)
6811 {
6812         int i, j, cubemapsize;
6813         unsigned char *cubemappixels, *image_buffer;
6814         rtexture_t *cubemaptexture;
6815         char name[256];
6816         // must start 0 so the first loadimagepixels has no requested width/height
6817         cubemapsize = 0;
6818         cubemappixels = NULL;
6819         cubemaptexture = NULL;
6820         // keep trying different suffix groups (posx, px, rt) until one loads
6821         for (j = 0;j < 3 && !cubemappixels;j++)
6822         {
6823                 // load the 6 images in the suffix group
6824                 for (i = 0;i < 6;i++)
6825                 {
6826                         // generate an image name based on the base and and suffix
6827                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6828                         // load it
6829                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6830                         {
6831                                 // an image loaded, make sure width and height are equal
6832                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6833                                 {
6834                                         // if this is the first image to load successfully, allocate the cubemap memory
6835                                         if (!cubemappixels && image_width >= 1)
6836                                         {
6837                                                 cubemapsize = image_width;
6838                                                 // note this clears to black, so unavailable sides are black
6839                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6840                                         }
6841                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6842                                         if (cubemappixels)
6843                                                 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);
6844                                 }
6845                                 else
6846                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6847                                 // free the image
6848                                 Mem_Free(image_buffer);
6849                         }
6850                 }
6851         }
6852         // if a cubemap loaded, upload it
6853         if (cubemappixels)
6854         {
6855                 if (developer_loading.integer)
6856                         Con_Printf("loading cubemap \"%s\"\n", basename);
6857
6858                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6859                 Mem_Free(cubemappixels);
6860         }
6861         else
6862         {
6863                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6864                 if (developer_loading.integer)
6865                 {
6866                         Con_Printf("(tried tried images ");
6867                         for (j = 0;j < 3;j++)
6868                                 for (i = 0;i < 6;i++)
6869                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6870                         Con_Print(" and was unable to find any of them).\n");
6871                 }
6872         }
6873         return cubemaptexture;
6874 }
6875
6876 rtexture_t *R_GetCubemap(const char *basename)
6877 {
6878         int i;
6879         for (i = 0;i < r_texture_numcubemaps;i++)
6880                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6881                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6882         if (i >= MAX_CUBEMAPS)
6883                 return r_texture_whitecube;
6884         r_texture_numcubemaps++;
6885         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6886         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6887         return r_texture_cubemaps[i].texture;
6888 }
6889
6890 void R_FreeCubemaps(void)
6891 {
6892         int i;
6893         for (i = 0;i < r_texture_numcubemaps;i++)
6894         {
6895                 if (developer_loading.integer)
6896                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6897                 if (r_texture_cubemaps[i].texture)
6898                         R_FreeTexture(r_texture_cubemaps[i].texture);
6899         }
6900         r_texture_numcubemaps = 0;
6901 }
6902
6903 void R_Main_FreeViewCache(void)
6904 {
6905         if (r_refdef.viewcache.entityvisible)
6906                 Mem_Free(r_refdef.viewcache.entityvisible);
6907         if (r_refdef.viewcache.world_pvsbits)
6908                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6909         if (r_refdef.viewcache.world_leafvisible)
6910                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6911         if (r_refdef.viewcache.world_surfacevisible)
6912                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6913         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6914 }
6915
6916 void R_Main_ResizeViewCache(void)
6917 {
6918         int numentities = r_refdef.scene.numentities;
6919         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6920         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6921         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6922         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6923         if (r_refdef.viewcache.maxentities < numentities)
6924         {
6925                 r_refdef.viewcache.maxentities = numentities;
6926                 if (r_refdef.viewcache.entityvisible)
6927                         Mem_Free(r_refdef.viewcache.entityvisible);
6928                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6929         }
6930         if (r_refdef.viewcache.world_numclusters != numclusters)
6931         {
6932                 r_refdef.viewcache.world_numclusters = numclusters;
6933                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6934                 if (r_refdef.viewcache.world_pvsbits)
6935                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6936                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6937         }
6938         if (r_refdef.viewcache.world_numleafs != numleafs)
6939         {
6940                 r_refdef.viewcache.world_numleafs = numleafs;
6941                 if (r_refdef.viewcache.world_leafvisible)
6942                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6943                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6944         }
6945         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6946         {
6947                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6948                 if (r_refdef.viewcache.world_surfacevisible)
6949                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6950                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6951         }
6952 }
6953
6954 extern rtexture_t *loadingscreentexture;
6955 void gl_main_start(void)
6956 {
6957         loadingscreentexture = NULL;
6958         r_texture_blanknormalmap = NULL;
6959         r_texture_white = NULL;
6960         r_texture_grey128 = NULL;
6961         r_texture_black = NULL;
6962         r_texture_whitecube = NULL;
6963         r_texture_normalizationcube = NULL;
6964         r_texture_fogattenuation = NULL;
6965         r_texture_fogheighttexture = NULL;
6966         r_texture_gammaramps = NULL;
6967         r_texture_numcubemaps = 0;
6968
6969         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6970         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6971
6972         switch(vid.renderpath)
6973         {
6974         case RENDERPATH_GL20:
6975         case RENDERPATH_CGGL:
6976         case RENDERPATH_D3D9:
6977         case RENDERPATH_D3D10:
6978         case RENDERPATH_D3D11:
6979                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6980                 Cvar_SetValueQuick(&gl_combine, 1);
6981                 Cvar_SetValueQuick(&r_glsl, 1);
6982                 r_loadnormalmap = true;
6983                 r_loadgloss = true;
6984                 r_loadfog = false;
6985                 break;
6986         case RENDERPATH_GL13:
6987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6988                 Cvar_SetValueQuick(&gl_combine, 1);
6989                 Cvar_SetValueQuick(&r_glsl, 0);
6990                 r_loadnormalmap = false;
6991                 r_loadgloss = false;
6992                 r_loadfog = true;
6993                 break;
6994         case RENDERPATH_GL11:
6995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6996                 Cvar_SetValueQuick(&gl_combine, 0);
6997                 Cvar_SetValueQuick(&r_glsl, 0);
6998                 r_loadnormalmap = false;
6999                 r_loadgloss = false;
7000                 r_loadfog = true;
7001                 break;
7002         }
7003
7004         R_AnimCache_Free();
7005         R_FrameData_Reset();
7006
7007         r_numqueries = 0;
7008         r_maxqueries = 0;
7009         memset(r_queries, 0, sizeof(r_queries));
7010
7011         r_qwskincache = NULL;
7012         r_qwskincache_size = 0;
7013
7014         // set up r_skinframe loading system for textures
7015         memset(&r_skinframe, 0, sizeof(r_skinframe));
7016         r_skinframe.loadsequence = 1;
7017         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7018
7019         r_main_texturepool = R_AllocTexturePool();
7020         R_BuildBlankTextures();
7021         R_BuildNoTexture();
7022         if (vid.support.arb_texture_cube_map)
7023         {
7024                 R_BuildWhiteCube();
7025                 R_BuildNormalizationCube();
7026         }
7027         r_texture_fogattenuation = NULL;
7028         r_texture_fogheighttexture = NULL;
7029         r_texture_gammaramps = NULL;
7030         //r_texture_fogintensity = NULL;
7031         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7032         memset(&r_waterstate, 0, sizeof(r_waterstate));
7033         r_glsl_permutation = NULL;
7034         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7035         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7036         glslshaderstring = NULL;
7037 #ifdef SUPPORTCG
7038         r_cg_permutation = NULL;
7039         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7040         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7041         cgshaderstring = NULL;
7042 #endif
7043 #ifdef SUPPORTD3D
7044         r_hlsl_permutation = NULL;
7045         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7046         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7047         hlslshaderstring = NULL;
7048 #endif
7049         memset(&r_svbsp, 0, sizeof (r_svbsp));
7050
7051         r_refdef.fogmasktable_density = 0;
7052 }
7053
7054 void gl_main_shutdown(void)
7055 {
7056         R_AnimCache_Free();
7057         R_FrameData_Reset();
7058
7059         R_Main_FreeViewCache();
7060
7061         switch(vid.renderpath)
7062         {
7063         case RENDERPATH_GL11:
7064         case RENDERPATH_GL13:
7065         case RENDERPATH_GL20:
7066         case RENDERPATH_CGGL:
7067                 if (r_maxqueries)
7068                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7069                 break;
7070         case RENDERPATH_D3D9:
7071                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7072                 break;
7073         case RENDERPATH_D3D10:
7074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7075                 break;
7076         case RENDERPATH_D3D11:
7077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7078                 break;
7079         }
7080
7081         r_numqueries = 0;
7082         r_maxqueries = 0;
7083         memset(r_queries, 0, sizeof(r_queries));
7084
7085         r_qwskincache = NULL;
7086         r_qwskincache_size = 0;
7087
7088         // clear out the r_skinframe state
7089         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7090         memset(&r_skinframe, 0, sizeof(r_skinframe));
7091
7092         if (r_svbsp.nodes)
7093                 Mem_Free(r_svbsp.nodes);
7094         memset(&r_svbsp, 0, sizeof (r_svbsp));
7095         R_FreeTexturePool(&r_main_texturepool);
7096         loadingscreentexture = NULL;
7097         r_texture_blanknormalmap = NULL;
7098         r_texture_white = NULL;
7099         r_texture_grey128 = NULL;
7100         r_texture_black = NULL;
7101         r_texture_whitecube = NULL;
7102         r_texture_normalizationcube = NULL;
7103         r_texture_fogattenuation = NULL;
7104         r_texture_fogheighttexture = NULL;
7105         r_texture_gammaramps = NULL;
7106         r_texture_numcubemaps = 0;
7107         //r_texture_fogintensity = NULL;
7108         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7109         memset(&r_waterstate, 0, sizeof(r_waterstate));
7110         R_GLSL_Restart_f();
7111 }
7112
7113 extern void CL_ParseEntityLump(char *entitystring);
7114 void gl_main_newmap(void)
7115 {
7116         // FIXME: move this code to client
7117         char *entities, entname[MAX_QPATH];
7118         if (r_qwskincache)
7119                 Mem_Free(r_qwskincache);
7120         r_qwskincache = NULL;
7121         r_qwskincache_size = 0;
7122         if (cl.worldmodel)
7123         {
7124                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7125                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7126                 {
7127                         CL_ParseEntityLump(entities);
7128                         Mem_Free(entities);
7129                         return;
7130                 }
7131                 if (cl.worldmodel->brush.entities)
7132                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7133         }
7134         R_Main_FreeViewCache();
7135
7136         R_FrameData_Reset();
7137 }
7138
7139 void GL_Main_Init(void)
7140 {
7141         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7142
7143         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7144         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7145         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7146         if (gamemode == GAME_NEHAHRA)
7147         {
7148                 Cvar_RegisterVariable (&gl_fogenable);
7149                 Cvar_RegisterVariable (&gl_fogdensity);
7150                 Cvar_RegisterVariable (&gl_fogred);
7151                 Cvar_RegisterVariable (&gl_foggreen);
7152                 Cvar_RegisterVariable (&gl_fogblue);
7153                 Cvar_RegisterVariable (&gl_fogstart);
7154                 Cvar_RegisterVariable (&gl_fogend);
7155                 Cvar_RegisterVariable (&gl_skyclip);
7156         }
7157         Cvar_RegisterVariable(&r_motionblur);
7158         Cvar_RegisterVariable(&r_motionblur_maxblur);
7159         Cvar_RegisterVariable(&r_motionblur_bmin);
7160         Cvar_RegisterVariable(&r_motionblur_vmin);
7161         Cvar_RegisterVariable(&r_motionblur_vmax);
7162         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7163         Cvar_RegisterVariable(&r_motionblur_randomize);
7164         Cvar_RegisterVariable(&r_damageblur);
7165         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7166         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7167         Cvar_RegisterVariable(&r_equalize_entities_by);
7168         Cvar_RegisterVariable(&r_equalize_entities_to);
7169         Cvar_RegisterVariable(&r_depthfirst);
7170         Cvar_RegisterVariable(&r_useinfinitefarclip);
7171         Cvar_RegisterVariable(&r_farclip_base);
7172         Cvar_RegisterVariable(&r_farclip_world);
7173         Cvar_RegisterVariable(&r_nearclip);
7174         Cvar_RegisterVariable(&r_showbboxes);
7175         Cvar_RegisterVariable(&r_showsurfaces);
7176         Cvar_RegisterVariable(&r_showtris);
7177         Cvar_RegisterVariable(&r_shownormals);
7178         Cvar_RegisterVariable(&r_showlighting);
7179         Cvar_RegisterVariable(&r_showshadowvolumes);
7180         Cvar_RegisterVariable(&r_showcollisionbrushes);
7181         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7182         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7183         Cvar_RegisterVariable(&r_showdisabledepthtest);
7184         Cvar_RegisterVariable(&r_drawportals);
7185         Cvar_RegisterVariable(&r_drawentities);
7186         Cvar_RegisterVariable(&r_draw2d);
7187         Cvar_RegisterVariable(&r_drawworld);
7188         Cvar_RegisterVariable(&r_cullentities_trace);
7189         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7190         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7191         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7192         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7193         Cvar_RegisterVariable(&r_drawviewmodel);
7194         Cvar_RegisterVariable(&r_drawexteriormodel);
7195         Cvar_RegisterVariable(&r_speeds);
7196         Cvar_RegisterVariable(&r_fullbrights);
7197         Cvar_RegisterVariable(&r_wateralpha);
7198         Cvar_RegisterVariable(&r_dynamic);
7199         Cvar_RegisterVariable(&r_fullbright);
7200         Cvar_RegisterVariable(&r_shadows);
7201         Cvar_RegisterVariable(&r_shadows_darken);
7202         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7203         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7204         Cvar_RegisterVariable(&r_shadows_throwdistance);
7205         Cvar_RegisterVariable(&r_shadows_throwdirection);
7206         Cvar_RegisterVariable(&r_shadows_focus);
7207         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7208         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7209         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7210         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7211         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7212         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7213         Cvar_RegisterVariable(&r_fog_exp2);
7214         Cvar_RegisterVariable(&r_drawfog);
7215         Cvar_RegisterVariable(&r_transparentdepthmasking);
7216         Cvar_RegisterVariable(&r_texture_dds_load);
7217         Cvar_RegisterVariable(&r_texture_dds_save);
7218         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7219         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7220         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7221         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7222         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7223         Cvar_RegisterVariable(&r_textureunits);
7224         Cvar_RegisterVariable(&gl_combine);
7225         Cvar_RegisterVariable(&r_glsl);
7226         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7227         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7228         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7229         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7230         Cvar_RegisterVariable(&r_glsl_postprocess);
7231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7235         Cvar_RegisterVariable(&r_water);
7236         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7237         Cvar_RegisterVariable(&r_water_clippingplanebias);
7238         Cvar_RegisterVariable(&r_water_refractdistort);
7239         Cvar_RegisterVariable(&r_water_reflectdistort);
7240         Cvar_RegisterVariable(&r_lerpsprites);
7241         Cvar_RegisterVariable(&r_lerpmodels);
7242         Cvar_RegisterVariable(&r_lerplightstyles);
7243         Cvar_RegisterVariable(&r_waterscroll);
7244         Cvar_RegisterVariable(&r_bloom);
7245         Cvar_RegisterVariable(&r_bloom_colorscale);
7246         Cvar_RegisterVariable(&r_bloom_brighten);
7247         Cvar_RegisterVariable(&r_bloom_blur);
7248         Cvar_RegisterVariable(&r_bloom_resolution);
7249         Cvar_RegisterVariable(&r_bloom_colorexponent);
7250         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7251         Cvar_RegisterVariable(&r_hdr);
7252         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7253         Cvar_RegisterVariable(&r_hdr_glowintensity);
7254         Cvar_RegisterVariable(&r_hdr_range);
7255         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7256         Cvar_RegisterVariable(&developer_texturelogging);
7257         Cvar_RegisterVariable(&gl_lightmaps);
7258         Cvar_RegisterVariable(&r_test);
7259         Cvar_RegisterVariable(&r_glsl_saturation);
7260         Cvar_RegisterVariable(&r_framedatasize);
7261         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7262                 Cvar_SetValue("r_fullbrights", 0);
7263         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7264
7265         Cvar_RegisterVariable(&r_track_sprites);
7266         Cvar_RegisterVariable(&r_track_sprites_flags);
7267         Cvar_RegisterVariable(&r_track_sprites_scalew);
7268         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7269         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7270         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7271 }
7272
7273 extern void R_Textures_Init(void);
7274 extern void GL_Draw_Init(void);
7275 extern void GL_Main_Init(void);
7276 extern void R_Shadow_Init(void);
7277 extern void R_Sky_Init(void);
7278 extern void GL_Surf_Init(void);
7279 extern void R_Particles_Init(void);
7280 extern void R_Explosion_Init(void);
7281 extern void gl_backend_init(void);
7282 extern void Sbar_Init(void);
7283 extern void R_LightningBeams_Init(void);
7284 extern void Mod_RenderInit(void);
7285 extern void Font_Init(void);
7286
7287 void Render_Init(void)
7288 {
7289         gl_backend_init();
7290         R_Textures_Init();
7291         GL_Main_Init();
7292         Font_Init();
7293         GL_Draw_Init();
7294         R_Shadow_Init();
7295         R_Sky_Init();
7296         GL_Surf_Init();
7297         Sbar_Init();
7298         R_Particles_Init();
7299         R_Explosion_Init();
7300         R_LightningBeams_Init();
7301         Mod_RenderInit();
7302 }
7303
7304 /*
7305 ===============
7306 GL_Init
7307 ===============
7308 */
7309 extern char *ENGINE_EXTENSIONS;
7310 void GL_Init (void)
7311 {
7312         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7313         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7314         gl_version = (const char *)qglGetString(GL_VERSION);
7315         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7316
7317         if (!gl_extensions)
7318                 gl_extensions = "";
7319         if (!gl_platformextensions)
7320                 gl_platformextensions = "";
7321
7322         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7323         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7324         Con_Printf("GL_VERSION: %s\n", gl_version);
7325         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7326         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7327
7328         VID_CheckExtensions();
7329
7330         // LordHavoc: report supported extensions
7331         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7332
7333         // clear to black (loading plaque will be seen over this)
7334         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7335 }
7336
7337 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7338 {
7339         int i;
7340         mplane_t *p;
7341         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7342         {
7343                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7344                 if (i == 4)
7345                         continue;
7346                 p = r_refdef.view.frustum + i;
7347                 switch(p->signbits)
7348                 {
7349                 default:
7350                 case 0:
7351                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7352                                 return true;
7353                         break;
7354                 case 1:
7355                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7356                                 return true;
7357                         break;
7358                 case 2:
7359                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7360                                 return true;
7361                         break;
7362                 case 3:
7363                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7364                                 return true;
7365                         break;
7366                 case 4:
7367                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7368                                 return true;
7369                         break;
7370                 case 5:
7371                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7372                                 return true;
7373                         break;
7374                 case 6:
7375                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7376                                 return true;
7377                         break;
7378                 case 7:
7379                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7380                                 return true;
7381                         break;
7382                 }
7383         }
7384         return false;
7385 }
7386
7387 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7388 {
7389         int i;
7390         const mplane_t *p;
7391         for (i = 0;i < numplanes;i++)
7392         {
7393                 p = planes + i;
7394                 switch(p->signbits)
7395                 {
7396                 default:
7397                 case 0:
7398                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7399                                 return true;
7400                         break;
7401                 case 1:
7402                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7403                                 return true;
7404                         break;
7405                 case 2:
7406                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7407                                 return true;
7408                         break;
7409                 case 3:
7410                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7411                                 return true;
7412                         break;
7413                 case 4:
7414                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7415                                 return true;
7416                         break;
7417                 case 5:
7418                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7419                                 return true;
7420                         break;
7421                 case 6:
7422                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7423                                 return true;
7424                         break;
7425                 case 7:
7426                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7427                                 return true;
7428                         break;
7429                 }
7430         }
7431         return false;
7432 }
7433
7434 //==================================================================================
7435
7436 // LordHavoc: this stores temporary data used within the same frame
7437
7438 qboolean r_framedata_failed;
7439 static size_t r_framedata_size;
7440 static size_t r_framedata_current;
7441 static void *r_framedata_base;
7442
7443 void R_FrameData_Reset(void)
7444 {
7445         if (r_framedata_base)
7446                 Mem_Free(r_framedata_base);
7447         r_framedata_base = NULL;
7448         r_framedata_size = 0;
7449         r_framedata_current = 0;
7450         r_framedata_failed = false;
7451 }
7452
7453 void R_FrameData_NewFrame(void)
7454 {
7455         size_t wantedsize;
7456         if (r_framedata_failed)
7457                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7458         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7459         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7460         if (r_framedata_size != wantedsize)
7461         {
7462                 r_framedata_size = wantedsize;
7463                 if (r_framedata_base)
7464                         Mem_Free(r_framedata_base);
7465                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7466         }
7467         r_framedata_current = 0;
7468         r_framedata_failed = false;
7469 }
7470
7471 void *R_FrameData_Alloc(size_t size)
7472 {
7473         void *data;
7474
7475         // align to 16 byte boundary
7476         size = (size + 15) & ~15;
7477         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7478         r_framedata_current += size;
7479
7480         // check overflow
7481         if (r_framedata_current > r_framedata_size)
7482                 r_framedata_failed = true;
7483
7484         // return NULL on everything after a failure
7485         if (r_framedata_failed)
7486                 return NULL;
7487
7488         return data;
7489 }
7490
7491 void *R_FrameData_Store(size_t size, void *data)
7492 {
7493         void *d = R_FrameData_Alloc(size);
7494         if (d)
7495                 memcpy(d, data, size);
7496         return d;
7497 }
7498
7499 //==================================================================================
7500
7501 // LordHavoc: animcache originally written by Echon, rewritten since then
7502
7503 /**
7504  * Animation cache prevents re-generating mesh data for an animated model
7505  * multiple times in one frame for lighting, shadowing, reflections, etc.
7506  */
7507
7508 void R_AnimCache_Free(void)
7509 {
7510 }
7511
7512 void R_AnimCache_ClearCache(void)
7513 {
7514         int i;
7515         entity_render_t *ent;
7516
7517         for (i = 0;i < r_refdef.scene.numentities;i++)
7518         {
7519                 ent = r_refdef.scene.entities[i];
7520                 ent->animcache_vertex3f = NULL;
7521                 ent->animcache_normal3f = NULL;
7522                 ent->animcache_svector3f = NULL;
7523                 ent->animcache_tvector3f = NULL;
7524                 ent->animcache_vertexposition = NULL;
7525                 ent->animcache_vertexmesh = NULL;
7526                 ent->animcache_vertexpositionbuffer = NULL;
7527                 ent->animcache_vertexmeshbuffer = NULL;
7528         }
7529 }
7530
7531 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7532 {
7533         int i;
7534
7535         // identical memory layout, so no need to allocate...
7536         // this also provides the vertexposition structure to everything, e.g.
7537         // depth masked rendering currently uses it even if having separate
7538         // arrays
7539         // NOTE: get rid of this optimization if changing it to e.g. 4f
7540         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7541
7542         // TODO:
7543         // get rid of following uses of VERTEXPOSITION, change to the array:
7544         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7545         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7546         // R_DrawTextureSurfaceList_DepthOnly
7547         // R_Q1BSP_DrawShadowMap
7548
7549         switch(vid.renderpath)
7550         {
7551         case RENDERPATH_GL20:
7552         case RENDERPATH_CGGL:
7553                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7554                 if (gl_mesh_separatearrays.integer)
7555                         return;
7556                 break;
7557         case RENDERPATH_D3D9:
7558         case RENDERPATH_D3D10:
7559         case RENDERPATH_D3D11:
7560                 // always need the meshbuffers
7561                 break;
7562         case RENDERPATH_GL13:
7563         case RENDERPATH_GL11:
7564                 // never need the meshbuffers
7565                 return;
7566         }
7567
7568         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7569                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7570         /*
7571         if (!ent->animcache_vertexposition)
7572                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7573         */
7574         if (ent->animcache_vertexposition)
7575         {
7576                 /*
7577                 for (i = 0;i < numvertices;i++)
7578                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7579                 */
7580                 // TODO: upload vertex buffer?
7581         }
7582         if (ent->animcache_vertexmesh)
7583         {
7584                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7585                 for (i = 0;i < numvertices;i++)
7586                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7587                 if (ent->animcache_svector3f)
7588                         for (i = 0;i < numvertices;i++)
7589                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7590                 if (ent->animcache_tvector3f)
7591                         for (i = 0;i < numvertices;i++)
7592                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7593                 if (ent->animcache_normal3f)
7594                         for (i = 0;i < numvertices;i++)
7595                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7596                 // TODO: upload vertex buffer?
7597         }
7598 }
7599
7600 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7601 {
7602         dp_model_t *model = ent->model;
7603         int numvertices;
7604         // see if it's already cached this frame
7605         if (ent->animcache_vertex3f)
7606         {
7607                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7608                 if (wantnormals || wanttangents)
7609                 {
7610                         if (ent->animcache_normal3f)
7611                                 wantnormals = false;
7612                         if (ent->animcache_svector3f)
7613                                 wanttangents = false;
7614                         if (wantnormals || wanttangents)
7615                         {
7616                                 numvertices = model->surfmesh.num_vertices;
7617                                 if (wantnormals)
7618                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7619                                 if (wanttangents)
7620                                 {
7621                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7622                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7623                                 }
7624                                 if (!r_framedata_failed)
7625                                 {
7626                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7627                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7628                                 }
7629                         }
7630                 }
7631         }
7632         else
7633         {
7634                 // see if this ent is worth caching
7635                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7636                         return false;
7637                 // get some memory for this entity and generate mesh data
7638                 numvertices = model->surfmesh.num_vertices;
7639                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7640                 if (wantnormals)
7641                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7642                 if (wanttangents)
7643                 {
7644                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7645                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7646                 }
7647                 if (!r_framedata_failed)
7648                 {
7649                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7650                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7651                 }
7652         }
7653         return !r_framedata_failed;
7654 }
7655
7656 void R_AnimCache_CacheVisibleEntities(void)
7657 {
7658         int i;
7659         qboolean wantnormals = true;
7660         qboolean wanttangents = !r_showsurfaces.integer;
7661
7662         switch(vid.renderpath)
7663         {
7664         case RENDERPATH_GL20:
7665         case RENDERPATH_CGGL:
7666         case RENDERPATH_D3D9:
7667         case RENDERPATH_D3D10:
7668         case RENDERPATH_D3D11:
7669                 break;
7670         case RENDERPATH_GL13:
7671         case RENDERPATH_GL11:
7672                 wanttangents = false;
7673                 break;
7674         }
7675
7676         if (r_shownormals.integer)
7677                 wanttangents = wantnormals = true;
7678
7679         // TODO: thread this
7680         // NOTE: R_PrepareRTLights() also caches entities
7681
7682         for (i = 0;i < r_refdef.scene.numentities;i++)
7683                 if (r_refdef.viewcache.entityvisible[i])
7684                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7685 }
7686
7687 //==================================================================================
7688
7689 static void R_View_UpdateEntityLighting (void)
7690 {
7691         int i;
7692         entity_render_t *ent;
7693         vec3_t tempdiffusenormal, avg;
7694         vec_t f, fa, fd, fdd;
7695         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7696
7697         for (i = 0;i < r_refdef.scene.numentities;i++)
7698         {
7699                 ent = r_refdef.scene.entities[i];
7700
7701                 // skip unseen models
7702                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7703                         continue;
7704
7705                 // skip bsp models
7706                 if (ent->model && ent->model->brush.num_leafs)
7707                 {
7708                         // TODO: use modellight for r_ambient settings on world?
7709                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7710                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7711                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7712                         continue;
7713                 }
7714
7715                 // fetch the lighting from the worldmodel data
7716                 VectorClear(ent->modellight_ambient);
7717                 VectorClear(ent->modellight_diffuse);
7718                 VectorClear(tempdiffusenormal);
7719                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7720                 {
7721                         vec3_t org;
7722                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7723                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7724                         if(ent->flags & RENDER_EQUALIZE)
7725                         {
7726                                 // first fix up ambient lighting...
7727                                 if(r_equalize_entities_minambient.value > 0)
7728                                 {
7729                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7730                                         if(fd > 0)
7731                                         {
7732                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7733                                                 if(fa < r_equalize_entities_minambient.value * fd)
7734                                                 {
7735                                                         // solve:
7736                                                         //   fa'/fd' = minambient
7737                                                         //   fa'+0.25*fd' = fa+0.25*fd
7738                                                         //   ...
7739                                                         //   fa' = fd' * minambient
7740                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7741                                                         //   ...
7742                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7743                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7744                                                         //   ...
7745                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7746                                                         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
7747                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7748                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7749                                                 }
7750                                         }
7751                                 }
7752
7753                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7754                                 {
7755                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7756                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7757                                         if(f > 0)
7758                                         {
7759                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7760                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7761                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7762                                         }
7763                                 }
7764                         }
7765                 }
7766                 else // highly rare
7767                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7768
7769                 // move the light direction into modelspace coordinates for lighting code
7770                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7771                 if(VectorLength2(ent->modellight_lightdir) == 0)
7772                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7773                 VectorNormalize(ent->modellight_lightdir);
7774         }
7775 }
7776
7777 #define MAX_LINEOFSIGHTTRACES 64
7778
7779 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7780 {
7781         int i;
7782         vec3_t boxmins, boxmaxs;
7783         vec3_t start;
7784         vec3_t end;
7785         dp_model_t *model = r_refdef.scene.worldmodel;
7786
7787         if (!model || !model->brush.TraceLineOfSight)
7788                 return true;
7789
7790         // expand the box a little
7791         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7792         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7793         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7794         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7795         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7796         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7797
7798         // return true if eye is inside enlarged box
7799         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7800                 return true;
7801
7802         // try center
7803         VectorCopy(eye, start);
7804         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7805         if (model->brush.TraceLineOfSight(model, start, end))
7806                 return true;
7807
7808         // try various random positions
7809         for (i = 0;i < numsamples;i++)
7810         {
7811                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7812                 if (model->brush.TraceLineOfSight(model, start, end))
7813                         return true;
7814         }
7815
7816         return false;
7817 }
7818
7819
7820 static void R_View_UpdateEntityVisible (void)
7821 {
7822         int i;
7823         int renderimask;
7824         int samples;
7825         entity_render_t *ent;
7826
7827         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7828                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7829                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7830                 :                                                          RENDER_EXTERIORMODEL;
7831         if (!r_drawviewmodel.integer)
7832                 renderimask |= RENDER_VIEWMODEL;
7833         if (!r_drawexteriormodel.integer)
7834                 renderimask |= RENDER_EXTERIORMODEL;
7835         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7836         {
7837                 // worldmodel can check visibility
7838                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7839                 for (i = 0;i < r_refdef.scene.numentities;i++)
7840                 {
7841                         ent = r_refdef.scene.entities[i];
7842                         if (!(ent->flags & renderimask))
7843                         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)))
7844                         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))
7845                                 r_refdef.viewcache.entityvisible[i] = true;
7846                 }
7847                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7848                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7849                 {
7850                         for (i = 0;i < r_refdef.scene.numentities;i++)
7851                         {
7852                                 ent = r_refdef.scene.entities[i];
7853                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7854                                 {
7855                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7856                                         if (samples < 0)
7857                                                 continue; // temp entities do pvs only
7858                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7859                                                 ent->last_trace_visibility = realtime;
7860                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7861                                                 r_refdef.viewcache.entityvisible[i] = 0;
7862                                 }
7863                         }
7864                 }
7865         }
7866         else
7867         {
7868                 // no worldmodel or it can't check visibility
7869                 for (i = 0;i < r_refdef.scene.numentities;i++)
7870                 {
7871                         ent = r_refdef.scene.entities[i];
7872                         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));
7873                 }
7874         }
7875 }
7876
7877 /// only used if skyrendermasked, and normally returns false
7878 int R_DrawBrushModelsSky (void)
7879 {
7880         int i, sky;
7881         entity_render_t *ent;
7882
7883         sky = false;
7884         for (i = 0;i < r_refdef.scene.numentities;i++)
7885         {
7886                 if (!r_refdef.viewcache.entityvisible[i])
7887                         continue;
7888                 ent = r_refdef.scene.entities[i];
7889                 if (!ent->model || !ent->model->DrawSky)
7890                         continue;
7891                 ent->model->DrawSky(ent);
7892                 sky = true;
7893         }
7894         return sky;
7895 }
7896
7897 static void R_DrawNoModel(entity_render_t *ent);
7898 static void R_DrawModels(void)
7899 {
7900         int i;
7901         entity_render_t *ent;
7902
7903         for (i = 0;i < r_refdef.scene.numentities;i++)
7904         {
7905                 if (!r_refdef.viewcache.entityvisible[i])
7906                         continue;
7907                 ent = r_refdef.scene.entities[i];
7908                 r_refdef.stats.entities++;
7909                 if (ent->model && ent->model->Draw != NULL)
7910                         ent->model->Draw(ent);
7911                 else
7912                         R_DrawNoModel(ent);
7913         }
7914 }
7915
7916 static void R_DrawModelsDepth(void)
7917 {
7918         int i;
7919         entity_render_t *ent;
7920
7921         for (i = 0;i < r_refdef.scene.numentities;i++)
7922         {
7923                 if (!r_refdef.viewcache.entityvisible[i])
7924                         continue;
7925                 ent = r_refdef.scene.entities[i];
7926                 if (ent->model && ent->model->DrawDepth != NULL)
7927                         ent->model->DrawDepth(ent);
7928         }
7929 }
7930
7931 static void R_DrawModelsDebug(void)
7932 {
7933         int i;
7934         entity_render_t *ent;
7935
7936         for (i = 0;i < r_refdef.scene.numentities;i++)
7937         {
7938                 if (!r_refdef.viewcache.entityvisible[i])
7939                         continue;
7940                 ent = r_refdef.scene.entities[i];
7941                 if (ent->model && ent->model->DrawDebug != NULL)
7942                         ent->model->DrawDebug(ent);
7943         }
7944 }
7945
7946 static void R_DrawModelsAddWaterPlanes(void)
7947 {
7948         int i;
7949         entity_render_t *ent;
7950
7951         for (i = 0;i < r_refdef.scene.numentities;i++)
7952         {
7953                 if (!r_refdef.viewcache.entityvisible[i])
7954                         continue;
7955                 ent = r_refdef.scene.entities[i];
7956                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7957                         ent->model->DrawAddWaterPlanes(ent);
7958         }
7959 }
7960
7961 static void R_View_SetFrustum(void)
7962 {
7963         int i;
7964         double slopex, slopey;
7965         vec3_t forward, left, up, origin;
7966
7967         // we can't trust r_refdef.view.forward and friends in reflected scenes
7968         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7969
7970 #if 0
7971         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7972         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7973         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7974         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7975         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7976         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7977         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7978         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7979         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7980         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7981         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7982         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7983 #endif
7984
7985 #if 0
7986         zNear = r_refdef.nearclip;
7987         nudge = 1.0 - 1.0 / (1<<23);
7988         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7989         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7990         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7991         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7992         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7993         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7994         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7995         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7996 #endif
7997
7998
7999
8000 #if 0
8001         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8002         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8003         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8004         r_refdef.view.frustum[0].dist = m[15] - m[12];
8005
8006         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8007         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8008         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8009         r_refdef.view.frustum[1].dist = m[15] + m[12];
8010
8011         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8012         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8013         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8014         r_refdef.view.frustum[2].dist = m[15] - m[13];
8015
8016         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8017         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8018         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8019         r_refdef.view.frustum[3].dist = m[15] + m[13];
8020
8021         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8022         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8023         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8024         r_refdef.view.frustum[4].dist = m[15] - m[14];
8025
8026         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8027         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8028         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8029         r_refdef.view.frustum[5].dist = m[15] + m[14];
8030 #endif
8031
8032         if (r_refdef.view.useperspective)
8033         {
8034                 slopex = 1.0 / r_refdef.view.frustum_x;
8035                 slopey = 1.0 / r_refdef.view.frustum_y;
8036                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8037                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8038                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8039                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8040                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8041
8042                 // Leaving those out was a mistake, those were in the old code, and they
8043                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8044                 // I couldn't reproduce it after adding those normalizations. --blub
8045                 VectorNormalize(r_refdef.view.frustum[0].normal);
8046                 VectorNormalize(r_refdef.view.frustum[1].normal);
8047                 VectorNormalize(r_refdef.view.frustum[2].normal);
8048                 VectorNormalize(r_refdef.view.frustum[3].normal);
8049
8050                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8051                 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]);
8052                 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]);
8053                 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]);
8054                 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]);
8055
8056                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8057                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8058                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8059                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8060                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8061         }
8062         else
8063         {
8064                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8065                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8066                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8067                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8068                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8069                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8070                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8071                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8072                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8073                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8074         }
8075         r_refdef.view.numfrustumplanes = 5;
8076
8077         if (r_refdef.view.useclipplane)
8078         {
8079                 r_refdef.view.numfrustumplanes = 6;
8080                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8081         }
8082
8083         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8084                 PlaneClassify(r_refdef.view.frustum + i);
8085
8086         // LordHavoc: note to all quake engine coders, Quake had a special case
8087         // for 90 degrees which assumed a square view (wrong), so I removed it,
8088         // Quake2 has it disabled as well.
8089
8090         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8091         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8092         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8093         //PlaneClassify(&frustum[0]);
8094
8095         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8096         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8097         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8098         //PlaneClassify(&frustum[1]);
8099
8100         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8101         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8102         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8103         //PlaneClassify(&frustum[2]);
8104
8105         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8106         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8107         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8108         //PlaneClassify(&frustum[3]);
8109
8110         // nearclip plane
8111         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8112         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8113         //PlaneClassify(&frustum[4]);
8114 }
8115
8116 void R_View_Update(void)
8117 {
8118         R_Main_ResizeViewCache();
8119         R_View_SetFrustum();
8120         R_View_WorldVisibility(r_refdef.view.useclipplane);
8121         R_View_UpdateEntityVisible();
8122         R_View_UpdateEntityLighting();
8123 }
8124
8125 void R_SetupView(qboolean allowwaterclippingplane)
8126 {
8127         const float *customclipplane = NULL;
8128         float plane[4];
8129         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8130         {
8131                 // LordHavoc: couldn't figure out how to make this approach the
8132                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8133                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8134                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8135                         dist = r_refdef.view.clipplane.dist;
8136                 plane[0] = r_refdef.view.clipplane.normal[0];
8137                 plane[1] = r_refdef.view.clipplane.normal[1];
8138                 plane[2] = r_refdef.view.clipplane.normal[2];
8139                 plane[3] = dist;
8140                 customclipplane = plane;
8141         }
8142
8143         if (!r_refdef.view.useperspective)
8144                 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);
8145         else if (vid.stencil && r_useinfinitefarclip.integer)
8146                 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);
8147         else
8148                 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);
8149         R_SetViewport(&r_refdef.view.viewport);
8150 }
8151
8152 void R_EntityMatrix(const matrix4x4_t *matrix)
8153 {
8154         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8155         {
8156                 gl_modelmatrixchanged = false;
8157                 gl_modelmatrix = *matrix;
8158                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8159                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8160                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8161                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8162                 CHECKGLERROR
8163                 switch(vid.renderpath)
8164                 {
8165                 case RENDERPATH_D3D9:
8166 #ifdef SUPPORTD3D
8167                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8168                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8169 #endif
8170                         break;
8171                 case RENDERPATH_D3D10:
8172                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8173                         break;
8174                 case RENDERPATH_D3D11:
8175                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8176                         break;
8177                 case RENDERPATH_GL20:
8178                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8179                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8180                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8181                         break;
8182                 case RENDERPATH_CGGL:
8183 #ifdef SUPPORTCG
8184                         CHECKCGERROR
8185                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8186                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8187                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8188 #endif
8189                         break;
8190                 case RENDERPATH_GL13:
8191                 case RENDERPATH_GL11:
8192                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8193                         break;
8194                 }
8195         }
8196 }
8197
8198 void R_ResetViewRendering2D(void)
8199 {
8200         r_viewport_t viewport;
8201         DrawQ_Finish();
8202
8203         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8204         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);
8205         R_SetViewport(&viewport);
8206         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8207         GL_Color(1, 1, 1, 1);
8208         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8209         GL_BlendFunc(GL_ONE, GL_ZERO);
8210         GL_AlphaTest(false);
8211         GL_ScissorTest(false);
8212         GL_DepthMask(false);
8213         GL_DepthRange(0, 1);
8214         GL_DepthTest(false);
8215         GL_DepthFunc(GL_LEQUAL);
8216         R_EntityMatrix(&identitymatrix);
8217         R_Mesh_ResetTextureState();
8218         GL_PolygonOffset(0, 0);
8219         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8220         switch(vid.renderpath)
8221         {
8222         case RENDERPATH_GL11:
8223         case RENDERPATH_GL13:
8224         case RENDERPATH_GL20:
8225         case RENDERPATH_CGGL:
8226                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8227                 break;
8228         case RENDERPATH_D3D9:
8229         case RENDERPATH_D3D10:
8230         case RENDERPATH_D3D11:
8231                 break;
8232         }
8233         GL_CullFace(GL_NONE);
8234 }
8235
8236 void R_ResetViewRendering3D(void)
8237 {
8238         DrawQ_Finish();
8239
8240         R_SetupView(true);
8241         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8242         GL_Color(1, 1, 1, 1);
8243         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8244         GL_BlendFunc(GL_ONE, GL_ZERO);
8245         GL_AlphaTest(false);
8246         GL_ScissorTest(true);
8247         GL_DepthMask(true);
8248         GL_DepthRange(0, 1);
8249         GL_DepthTest(true);
8250         GL_DepthFunc(GL_LEQUAL);
8251         R_EntityMatrix(&identitymatrix);
8252         R_Mesh_ResetTextureState();
8253         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8254         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8255         switch(vid.renderpath)
8256         {
8257         case RENDERPATH_GL11:
8258         case RENDERPATH_GL13:
8259         case RENDERPATH_GL20:
8260         case RENDERPATH_CGGL:
8261                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8262                 break;
8263         case RENDERPATH_D3D9:
8264         case RENDERPATH_D3D10:
8265         case RENDERPATH_D3D11:
8266                 break;
8267         }
8268         GL_CullFace(r_refdef.view.cullface_back);
8269 }
8270
8271 /*
8272 ================
8273 R_RenderView_UpdateViewVectors
8274 ================
8275 */
8276 static void R_RenderView_UpdateViewVectors(void)
8277 {
8278         // break apart the view matrix into vectors for various purposes
8279         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8280         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8281         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8282         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8283         // make an inverted copy of the view matrix for tracking sprites
8284         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8285 }
8286
8287 void R_RenderScene(void);
8288 void R_RenderWaterPlanes(void);
8289
8290 static void R_Water_StartFrame(void)
8291 {
8292         int i;
8293         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8294         r_waterstate_waterplane_t *p;
8295
8296         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8297                 return;
8298
8299         switch(vid.renderpath)
8300         {
8301         case RENDERPATH_GL20:
8302         case RENDERPATH_CGGL:
8303         case RENDERPATH_D3D9:
8304         case RENDERPATH_D3D10:
8305         case RENDERPATH_D3D11:
8306                 break;
8307         case RENDERPATH_GL13:
8308         case RENDERPATH_GL11:
8309                 return;
8310         }
8311
8312         // set waterwidth and waterheight to the water resolution that will be
8313         // used (often less than the screen resolution for faster rendering)
8314         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8315         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8316
8317         // calculate desired texture sizes
8318         // can't use water if the card does not support the texture size
8319         if (!r_water.integer || r_showsurfaces.integer)
8320                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8321         else if (vid.support.arb_texture_non_power_of_two)
8322         {
8323                 texturewidth = waterwidth;
8324                 textureheight = waterheight;
8325                 camerawidth = waterwidth;
8326                 cameraheight = waterheight;
8327         }
8328         else
8329         {
8330                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8331                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8332                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8333                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8334         }
8335
8336         // allocate textures as needed
8337         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8338         {
8339                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8340                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8341                 {
8342                         if (p->texture_refraction)
8343                                 R_FreeTexture(p->texture_refraction);
8344                         p->texture_refraction = NULL;
8345                         if (p->texture_reflection)
8346                                 R_FreeTexture(p->texture_reflection);
8347                         p->texture_reflection = NULL;
8348                         if (p->texture_camera)
8349                                 R_FreeTexture(p->texture_camera);
8350                         p->texture_camera = NULL;
8351                 }
8352                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8353                 r_waterstate.texturewidth = texturewidth;
8354                 r_waterstate.textureheight = textureheight;
8355                 r_waterstate.camerawidth = camerawidth;
8356                 r_waterstate.cameraheight = cameraheight;
8357         }
8358
8359         if (r_waterstate.texturewidth)
8360         {
8361                 r_waterstate.enabled = true;
8362
8363                 // when doing a reduced render (HDR) we want to use a smaller area
8364                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8365                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8366
8367                 // set up variables that will be used in shader setup
8368                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8369                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8370                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8371                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8372         }
8373
8374         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8375         r_waterstate.numwaterplanes = 0;
8376 }
8377
8378 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8379 {
8380         int triangleindex, planeindex;
8381         const int *e;
8382         vec3_t vert[3];
8383         vec3_t normal;
8384         vec3_t center;
8385         mplane_t plane;
8386         r_waterstate_waterplane_t *p;
8387         texture_t *t = R_GetCurrentTexture(surface->texture);
8388
8389         // just use the first triangle with a valid normal for any decisions
8390         VectorClear(normal);
8391         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8392         {
8393                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8394                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8395                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8396                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8397                 if (VectorLength2(normal) >= 0.001)
8398                         break;
8399         }
8400
8401         VectorCopy(normal, plane.normal);
8402         VectorNormalize(plane.normal);
8403         plane.dist = DotProduct(vert[0], plane.normal);
8404         PlaneClassify(&plane);
8405         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8406         {
8407                 // skip backfaces (except if nocullface is set)
8408                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8409                         return;
8410                 VectorNegate(plane.normal, plane.normal);
8411                 plane.dist *= -1;
8412                 PlaneClassify(&plane);
8413         }
8414
8415
8416         // find a matching plane if there is one
8417         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8418                 if(p->camera_entity == t->camera_entity)
8419                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8420                                 break;
8421         if (planeindex >= r_waterstate.maxwaterplanes)
8422                 return; // nothing we can do, out of planes
8423
8424         // if this triangle does not fit any known plane rendered this frame, add one
8425         if (planeindex >= r_waterstate.numwaterplanes)
8426         {
8427                 // store the new plane
8428                 r_waterstate.numwaterplanes++;
8429                 p->plane = plane;
8430                 // clear materialflags and pvs
8431                 p->materialflags = 0;
8432                 p->pvsvalid = false;
8433                 p->camera_entity = t->camera_entity;
8434         }
8435         // merge this surface's materialflags into the waterplane
8436         p->materialflags |= t->currentmaterialflags;
8437         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8438         {
8439                 // merge this surface's PVS into the waterplane
8440                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8441                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8442                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8443                 {
8444                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8445                         p->pvsvalid = true;
8446                 }
8447         }
8448 }
8449
8450 static void R_Water_ProcessPlanes(void)
8451 {
8452         r_refdef_view_t originalview;
8453         r_refdef_view_t myview;
8454         int planeindex;
8455         r_waterstate_waterplane_t *p;
8456         vec3_t visorigin;
8457
8458         originalview = r_refdef.view;
8459
8460         // make sure enough textures are allocated
8461         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8462         {
8463                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8464                 {
8465                         if (!p->texture_refraction)
8466                                 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);
8467                         if (!p->texture_refraction)
8468                                 goto error;
8469                 }
8470                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8471                 {
8472                         if (!p->texture_camera)
8473                                 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);
8474                         if (!p->texture_camera)
8475                                 goto error;
8476                 }
8477
8478                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8479                 {
8480                         if (!p->texture_reflection)
8481                                 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);
8482                         if (!p->texture_reflection)
8483                                 goto error;
8484                 }
8485         }
8486
8487         // render views
8488         r_refdef.view = originalview;
8489         r_refdef.view.showdebug = false;
8490         r_refdef.view.width = r_waterstate.waterwidth;
8491         r_refdef.view.height = r_waterstate.waterheight;
8492         r_refdef.view.useclipplane = true;
8493         myview = r_refdef.view;
8494         r_waterstate.renderingscene = true;
8495         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8496         {
8497                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8498                 {
8499                         r_refdef.view = myview;
8500                         // render reflected scene and copy into texture
8501                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8502                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8503                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8504                         r_refdef.view.clipplane = p->plane;
8505                         // reverse the cullface settings for this render
8506                         r_refdef.view.cullface_front = GL_FRONT;
8507                         r_refdef.view.cullface_back = GL_BACK;
8508                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8509                         {
8510                                 r_refdef.view.usecustompvs = true;
8511                                 if (p->pvsvalid)
8512                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8513                                 else
8514                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8515                         }
8516
8517                         R_ResetViewRendering3D();
8518                         R_ClearScreen(r_refdef.fogenabled);
8519                         R_View_Update();
8520                         R_RenderScene();
8521
8522                         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);
8523                 }
8524
8525                 // render the normal view scene and copy into texture
8526                 // (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)
8527                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8528                 {
8529                         r_waterstate.renderingrefraction = true;
8530                         r_refdef.view = myview;
8531
8532                         r_refdef.view.clipplane = p->plane;
8533                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8534                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8535
8536                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8537                         {
8538                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8539                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8540                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8541                                 R_RenderView_UpdateViewVectors();
8542                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8543                                 {
8544                                         r_refdef.view.usecustompvs = true;
8545                                         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);
8546                                 }
8547                         }
8548
8549                         PlaneClassify(&r_refdef.view.clipplane);
8550
8551                         R_ResetViewRendering3D();
8552                         R_ClearScreen(r_refdef.fogenabled);
8553                         R_View_Update();
8554                         R_RenderScene();
8555
8556                         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);
8557                         r_waterstate.renderingrefraction = false;
8558                 }
8559                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8560                 {
8561                         r_refdef.view = myview;
8562
8563                         r_refdef.view.clipplane = p->plane;
8564                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8565                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8566
8567                         r_refdef.view.width = r_waterstate.camerawidth;
8568                         r_refdef.view.height = r_waterstate.cameraheight;
8569                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8570                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8571
8572                         if(p->camera_entity)
8573                         {
8574                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8575                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8576                         }
8577
8578                         // reverse the cullface settings for this render
8579                         r_refdef.view.cullface_front = GL_FRONT;
8580                         r_refdef.view.cullface_back = GL_BACK;
8581                         // also reverse the view matrix
8582                         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
8583                         R_RenderView_UpdateViewVectors();
8584                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8585                         {
8586                                 r_refdef.view.usecustompvs = true;
8587                                 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);
8588                         }
8589                         
8590                         // camera needs no clipplane
8591                         r_refdef.view.useclipplane = false;
8592
8593                         PlaneClassify(&r_refdef.view.clipplane);
8594
8595                         R_ResetViewRendering3D();
8596                         R_ClearScreen(r_refdef.fogenabled);
8597                         R_View_Update();
8598                         R_RenderScene();
8599
8600                         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);
8601                         r_waterstate.renderingrefraction = false;
8602                 }
8603
8604         }
8605         r_waterstate.renderingscene = false;
8606         r_refdef.view = originalview;
8607         R_ResetViewRendering3D();
8608         R_ClearScreen(r_refdef.fogenabled);
8609         R_View_Update();
8610         return;
8611 error:
8612         r_refdef.view = originalview;
8613         r_waterstate.renderingscene = false;
8614         Cvar_SetValueQuick(&r_water, 0);
8615         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8616         return;
8617 }
8618
8619 void R_Bloom_StartFrame(void)
8620 {
8621         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8622
8623         switch(vid.renderpath)
8624         {
8625         case RENDERPATH_GL20:
8626         case RENDERPATH_CGGL:
8627         case RENDERPATH_D3D9:
8628         case RENDERPATH_D3D10:
8629         case RENDERPATH_D3D11:
8630                 break;
8631         case RENDERPATH_GL13:
8632         case RENDERPATH_GL11:
8633                 return;
8634         }
8635
8636         // set bloomwidth and bloomheight to the bloom resolution that will be
8637         // used (often less than the screen resolution for faster rendering)
8638         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8639         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8640         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8641         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8642         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8643
8644         // calculate desired texture sizes
8645         if (vid.support.arb_texture_non_power_of_two)
8646         {
8647                 screentexturewidth = r_refdef.view.width;
8648                 screentextureheight = r_refdef.view.height;
8649                 bloomtexturewidth = r_bloomstate.bloomwidth;
8650                 bloomtextureheight = r_bloomstate.bloomheight;
8651         }
8652         else
8653         {
8654                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8655                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8656                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8657                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8658         }
8659
8660         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))
8661         {
8662                 Cvar_SetValueQuick(&r_hdr, 0);
8663                 Cvar_SetValueQuick(&r_bloom, 0);
8664                 Cvar_SetValueQuick(&r_motionblur, 0);
8665                 Cvar_SetValueQuick(&r_damageblur, 0);
8666         }
8667
8668         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)))
8669                 screentexturewidth = screentextureheight = 0;
8670         if (!r_hdr.integer && !r_bloom.integer)
8671                 bloomtexturewidth = bloomtextureheight = 0;
8672
8673         // allocate textures as needed
8674         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8675         {
8676                 if (r_bloomstate.texture_screen)
8677                         R_FreeTexture(r_bloomstate.texture_screen);
8678                 r_bloomstate.texture_screen = NULL;
8679                 r_bloomstate.screentexturewidth = screentexturewidth;
8680                 r_bloomstate.screentextureheight = screentextureheight;
8681                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8682                         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);
8683         }
8684         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8685         {
8686                 if (r_bloomstate.texture_bloom)
8687                         R_FreeTexture(r_bloomstate.texture_bloom);
8688                 r_bloomstate.texture_bloom = NULL;
8689                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8690                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8691                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8692                         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);
8693         }
8694
8695         // when doing a reduced render (HDR) we want to use a smaller area
8696         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8697         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8698         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8699         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8700         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8701
8702         // set up a texcoord array for the full resolution screen image
8703         // (we have to keep this around to copy back during final render)
8704         r_bloomstate.screentexcoord2f[0] = 0;
8705         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8706         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8707         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8708         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8709         r_bloomstate.screentexcoord2f[5] = 0;
8710         r_bloomstate.screentexcoord2f[6] = 0;
8711         r_bloomstate.screentexcoord2f[7] = 0;
8712
8713         // set up a texcoord array for the reduced resolution bloom image
8714         // (which will be additive blended over the screen image)
8715         r_bloomstate.bloomtexcoord2f[0] = 0;
8716         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8717         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8718         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8719         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8720         r_bloomstate.bloomtexcoord2f[5] = 0;
8721         r_bloomstate.bloomtexcoord2f[6] = 0;
8722         r_bloomstate.bloomtexcoord2f[7] = 0;
8723
8724         switch(vid.renderpath)
8725         {
8726         case RENDERPATH_GL11:
8727         case RENDERPATH_GL13:
8728         case RENDERPATH_GL20:
8729         case RENDERPATH_CGGL:
8730                 break;
8731         case RENDERPATH_D3D9:
8732         case RENDERPATH_D3D10:
8733         case RENDERPATH_D3D11:
8734                 {
8735                         int i;
8736                         for (i = 0;i < 4;i++)
8737                         {
8738                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8739                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8740                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8741                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8742                         }
8743                 }
8744                 break;
8745         }
8746
8747         if (r_hdr.integer || r_bloom.integer)
8748         {
8749                 r_bloomstate.enabled = true;
8750                 r_bloomstate.hdr = r_hdr.integer != 0;
8751         }
8752
8753         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);
8754 }
8755
8756 void R_Bloom_CopyBloomTexture(float colorscale)
8757 {
8758         r_refdef.stats.bloom++;
8759
8760         // scale down screen texture to the bloom texture size
8761         CHECKGLERROR
8762         R_SetViewport(&r_bloomstate.viewport);
8763         GL_BlendFunc(GL_ONE, GL_ZERO);
8764         GL_Color(colorscale, colorscale, colorscale, 1);
8765         // 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...
8766         switch(vid.renderpath)
8767         {
8768         case RENDERPATH_GL11:
8769         case RENDERPATH_GL13:
8770         case RENDERPATH_GL20:
8771         case RENDERPATH_CGGL:
8772                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8773                 break;
8774         case RENDERPATH_D3D9:
8775         case RENDERPATH_D3D10:
8776         case RENDERPATH_D3D11:
8777                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8778                 break;
8779         }
8780         // TODO: do boxfilter scale-down in shader?
8781         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8782         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8783         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8784
8785         // we now have a bloom image in the framebuffer
8786         // copy it into the bloom image texture for later processing
8787         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);
8788         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8789 }
8790
8791 void R_Bloom_CopyHDRTexture(void)
8792 {
8793         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);
8794         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8795 }
8796
8797 void R_Bloom_MakeTexture(void)
8798 {
8799         int x, range, dir;
8800         float xoffset, yoffset, r, brighten;
8801
8802         r_refdef.stats.bloom++;
8803
8804         R_ResetViewRendering2D();
8805
8806         // we have a bloom image in the framebuffer
8807         CHECKGLERROR
8808         R_SetViewport(&r_bloomstate.viewport);
8809
8810         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8811         {
8812                 x *= 2;
8813                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8814                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8815                 GL_Color(r,r,r,1);
8816                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8817                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8818                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8819                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8820
8821                 // copy the vertically blurred bloom view to a texture
8822                 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);
8823                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8824         }
8825
8826         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8827         brighten = r_bloom_brighten.value;
8828         if (r_hdr.integer)
8829                 brighten *= r_hdr_range.value;
8830         brighten = sqrt(brighten);
8831         if(range >= 1)
8832                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8833         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8834
8835         for (dir = 0;dir < 2;dir++)
8836         {
8837                 // blend on at multiple vertical offsets to achieve a vertical blur
8838                 // TODO: do offset blends using GLSL
8839                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8840                 GL_BlendFunc(GL_ONE, GL_ZERO);
8841                 for (x = -range;x <= range;x++)
8842                 {
8843                         if (!dir){xoffset = 0;yoffset = x;}
8844                         else {xoffset = x;yoffset = 0;}
8845                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8846                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8847                         // compute a texcoord array with the specified x and y offset
8848                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8849                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8850                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8851                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8852                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8853                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8854                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8855                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8856                         // this r value looks like a 'dot' particle, fading sharply to
8857                         // black at the edges
8858                         // (probably not realistic but looks good enough)
8859                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8860                         //r = brighten/(range*2+1);
8861                         r = brighten / (range * 2 + 1);
8862                         if(range >= 1)
8863                                 r *= (1 - x*x/(float)(range*range));
8864                         GL_Color(r, r, r, 1);
8865                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8866                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8867                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8868                         GL_BlendFunc(GL_ONE, GL_ONE);
8869                 }
8870
8871                 // copy the vertically blurred bloom view to a texture
8872                 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);
8873                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8874         }
8875 }
8876
8877 void R_HDR_RenderBloomTexture(void)
8878 {
8879         int oldwidth, oldheight;
8880         float oldcolorscale;
8881
8882         oldcolorscale = r_refdef.view.colorscale;
8883         oldwidth = r_refdef.view.width;
8884         oldheight = r_refdef.view.height;
8885         r_refdef.view.width = r_bloomstate.bloomwidth;
8886         r_refdef.view.height = r_bloomstate.bloomheight;
8887
8888         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8889         // TODO: add exposure compensation features
8890         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8891
8892         r_refdef.view.showdebug = false;
8893         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8894
8895         R_ResetViewRendering3D();
8896
8897         R_ClearScreen(r_refdef.fogenabled);
8898         if (r_timereport_active)
8899                 R_TimeReport("HDRclear");
8900
8901         R_View_Update();
8902         if (r_timereport_active)
8903                 R_TimeReport("visibility");
8904
8905         // only do secondary renders with HDR if r_hdr is 2 or higher
8906         r_waterstate.numwaterplanes = 0;
8907         if (r_waterstate.enabled && r_hdr.integer >= 2)
8908                 R_RenderWaterPlanes();
8909
8910         r_refdef.view.showdebug = true;
8911         R_RenderScene();
8912         r_waterstate.numwaterplanes = 0;
8913
8914         R_ResetViewRendering2D();
8915
8916         R_Bloom_CopyHDRTexture();
8917         R_Bloom_MakeTexture();
8918
8919         // restore the view settings
8920         r_refdef.view.width = oldwidth;
8921         r_refdef.view.height = oldheight;
8922         r_refdef.view.colorscale = oldcolorscale;
8923
8924         R_ResetViewRendering3D();
8925
8926         R_ClearScreen(r_refdef.fogenabled);
8927         if (r_timereport_active)
8928                 R_TimeReport("viewclear");
8929 }
8930
8931 static void R_BlendView(void)
8932 {
8933         unsigned int permutation;
8934         float uservecs[4][4];
8935
8936         switch (vid.renderpath)
8937         {
8938         case RENDERPATH_GL20:
8939         case RENDERPATH_CGGL:
8940         case RENDERPATH_D3D9:
8941         case RENDERPATH_D3D10:
8942         case RENDERPATH_D3D11:
8943                 permutation =
8944                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8945                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8946                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8947                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8948                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8949
8950                 if (r_bloomstate.texture_screen)
8951                 {
8952                         // make sure the buffer is available
8953                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8954
8955                         R_ResetViewRendering2D();
8956
8957                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8958                         {
8959                                 // declare variables
8960                                 float speed;
8961                                 static float avgspeed;
8962
8963                                 speed = VectorLength(cl.movement_velocity);
8964
8965                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8966                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8967
8968                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8969                                 speed = bound(0, speed, 1);
8970                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8971
8972                                 // calculate values into a standard alpha
8973                                 cl.motionbluralpha = 1 - exp(-
8974                                                 (
8975                                                  (r_motionblur.value * speed / 80)
8976                                                  +
8977                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8978                                                 )
8979                                                 /
8980                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8981                                            );
8982
8983                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8984                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8985                                 // apply the blur
8986                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8987                                 {
8988                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8989                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8990                                         switch(vid.renderpath)
8991                                         {
8992                                         case RENDERPATH_GL11:
8993                                         case RENDERPATH_GL13:
8994                                         case RENDERPATH_GL20:
8995                                         case RENDERPATH_CGGL:
8996                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8997                                                 break;
8998                                         case RENDERPATH_D3D9:
8999                                         case RENDERPATH_D3D10:
9000                                         case RENDERPATH_D3D11:
9001                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9002                                                 break;
9003                                         }
9004                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9005                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9006                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9007                                 }
9008                         }
9009
9010                         // copy view into the screen texture
9011                         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);
9012                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9013                 }
9014                 else if (!r_bloomstate.texture_bloom)
9015                 {
9016                         // we may still have to do view tint...
9017                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9018                         {
9019                                 // apply a color tint to the whole view
9020                                 R_ResetViewRendering2D();
9021                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9022                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9023                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9024                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9025                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9026                         }
9027                         break; // no screen processing, no bloom, skip it
9028                 }
9029
9030                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9031                 {
9032                         // render simple bloom effect
9033                         // copy the screen and shrink it and darken it for the bloom process
9034                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9035                         // make the bloom texture
9036                         R_Bloom_MakeTexture();
9037                 }
9038
9039 #if _MSC_VER >= 1400
9040 #define sscanf sscanf_s
9041 #endif
9042                 memset(uservecs, 0, sizeof(uservecs));
9043                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9044                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9045                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9046                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9047
9048                 R_ResetViewRendering2D();
9049                 GL_Color(1, 1, 1, 1);
9050                 GL_BlendFunc(GL_ONE, GL_ZERO);
9051
9052                 switch(vid.renderpath)
9053                 {
9054                 case RENDERPATH_GL20:
9055                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9056                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9057                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9058                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9059                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9060                         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]);
9061                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9062                         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]);
9063                         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]);
9064                         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]);
9065                         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]);
9066                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9067                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9068                         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);
9069                         break;
9070                 case RENDERPATH_CGGL:
9071 #ifdef SUPPORTCG
9072                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9073                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9074                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9075                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9076                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9077                         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
9078                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9079                         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
9080                         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
9081                         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
9082                         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
9083                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9084                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9085                         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);
9086 #endif
9087                         break;
9088                 case RENDERPATH_D3D9:
9089 #ifdef SUPPORTD3D
9090                         // 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...
9091                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9092                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9093                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9094                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9095                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9096                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9097                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9098                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9099                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9100                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9101                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9102                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9103                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9104                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9105 #endif
9106                         break;
9107                 case RENDERPATH_D3D10:
9108                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9109                         break;
9110                 case RENDERPATH_D3D11:
9111                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9112                         break;
9113                 default:
9114                         break;
9115                 }
9116                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9117                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9118                 break;
9119         case RENDERPATH_GL13:
9120         case RENDERPATH_GL11:
9121                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9122                 {
9123                         // apply a color tint to the whole view
9124                         R_ResetViewRendering2D();
9125                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9126                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9127                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9128                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9129                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9130                 }
9131                 break;
9132         }
9133 }
9134
9135 matrix4x4_t r_waterscrollmatrix;
9136
9137 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9138 {
9139         if (r_refdef.fog_density)
9140         {
9141                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9142                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9143                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9144
9145                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9146                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9147                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9148                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9149
9150                 {
9151                         vec3_t fogvec;
9152                         VectorCopy(r_refdef.fogcolor, fogvec);
9153                         //   color.rgb *= ContrastBoost * SceneBrightness;
9154                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9155                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9156                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9157                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9158                 }
9159         }
9160 }
9161
9162 void R_UpdateVariables(void)
9163 {
9164         R_Textures_Frame();
9165
9166         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9167
9168         r_refdef.farclip = r_farclip_base.value;
9169         if (r_refdef.scene.worldmodel)
9170                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9171         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9172
9173         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9174                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9175         r_refdef.polygonfactor = 0;
9176         r_refdef.polygonoffset = 0;
9177         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9178         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9179
9180         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9181         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9182         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9183         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9184         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9185         if (r_showsurfaces.integer)
9186         {
9187                 r_refdef.scene.rtworld = false;
9188                 r_refdef.scene.rtworldshadows = false;
9189                 r_refdef.scene.rtdlight = false;
9190                 r_refdef.scene.rtdlightshadows = false;
9191                 r_refdef.lightmapintensity = 0;
9192         }
9193
9194         if (gamemode == GAME_NEHAHRA)
9195         {
9196                 if (gl_fogenable.integer)
9197                 {
9198                         r_refdef.oldgl_fogenable = true;
9199                         r_refdef.fog_density = gl_fogdensity.value;
9200                         r_refdef.fog_red = gl_fogred.value;
9201                         r_refdef.fog_green = gl_foggreen.value;
9202                         r_refdef.fog_blue = gl_fogblue.value;
9203                         r_refdef.fog_alpha = 1;
9204                         r_refdef.fog_start = 0;
9205                         r_refdef.fog_end = gl_skyclip.value;
9206                         r_refdef.fog_height = 1<<30;
9207                         r_refdef.fog_fadedepth = 128;
9208                 }
9209                 else if (r_refdef.oldgl_fogenable)
9210                 {
9211                         r_refdef.oldgl_fogenable = false;
9212                         r_refdef.fog_density = 0;
9213                         r_refdef.fog_red = 0;
9214                         r_refdef.fog_green = 0;
9215                         r_refdef.fog_blue = 0;
9216                         r_refdef.fog_alpha = 0;
9217                         r_refdef.fog_start = 0;
9218                         r_refdef.fog_end = 0;
9219                         r_refdef.fog_height = 1<<30;
9220                         r_refdef.fog_fadedepth = 128;
9221                 }
9222         }
9223
9224         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9225         r_refdef.fog_start = max(0, r_refdef.fog_start);
9226         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9227
9228         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9229
9230         if (r_refdef.fog_density && r_drawfog.integer)
9231         {
9232                 r_refdef.fogenabled = true;
9233                 // this is the point where the fog reaches 0.9986 alpha, which we
9234                 // consider a good enough cutoff point for the texture
9235                 // (0.9986 * 256 == 255.6)
9236                 if (r_fog_exp2.integer)
9237                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9238                 else
9239                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9240                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9241                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9242                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9243                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9244                         R_BuildFogHeightTexture();
9245                 // fog color was already set
9246                 // update the fog texture
9247                 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)
9248                         R_BuildFogTexture();
9249                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9250                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9251         }
9252         else
9253                 r_refdef.fogenabled = false;
9254
9255         switch(vid.renderpath)
9256         {
9257         case RENDERPATH_GL20:
9258         case RENDERPATH_CGGL:
9259         case RENDERPATH_D3D9:
9260         case RENDERPATH_D3D10:
9261         case RENDERPATH_D3D11:
9262                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9263                 {
9264                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9265                         {
9266                                 // build GLSL gamma texture
9267 #define RAMPWIDTH 256
9268                                 unsigned short ramp[RAMPWIDTH * 3];
9269                                 unsigned char rampbgr[RAMPWIDTH][4];
9270                                 int i;
9271
9272                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9273
9274                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9275                                 for(i = 0; i < RAMPWIDTH; ++i)
9276                                 {
9277                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9278                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9279                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9280                                         rampbgr[i][3] = 0;
9281                                 }
9282                                 if (r_texture_gammaramps)
9283                                 {
9284                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9285                                 }
9286                                 else
9287                                 {
9288                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9289                                 }
9290                         }
9291                 }
9292                 else
9293                 {
9294                         // remove GLSL gamma texture
9295                 }
9296                 break;
9297         case RENDERPATH_GL13:
9298         case RENDERPATH_GL11:
9299                 break;
9300         }
9301 }
9302
9303 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9304 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9305 /*
9306 ================
9307 R_SelectScene
9308 ================
9309 */
9310 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9311         if( scenetype != r_currentscenetype ) {
9312                 // store the old scenetype
9313                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9314                 r_currentscenetype = scenetype;
9315                 // move in the new scene
9316                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9317         }
9318 }
9319
9320 /*
9321 ================
9322 R_GetScenePointer
9323 ================
9324 */
9325 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9326 {
9327         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9328         if( scenetype == r_currentscenetype ) {
9329                 return &r_refdef.scene;
9330         } else {
9331                 return &r_scenes_store[ scenetype ];
9332         }
9333 }
9334
9335 /*
9336 ================
9337 R_RenderView
9338 ================
9339 */
9340 void R_RenderView(void)
9341 {
9342         if (r_timereport_active)
9343                 R_TimeReport("start");
9344         r_textureframe++; // used only by R_GetCurrentTexture
9345         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9346
9347         if (!r_drawentities.integer)
9348                 r_refdef.scene.numentities = 0;
9349
9350         R_AnimCache_ClearCache();
9351         R_FrameData_NewFrame();
9352
9353         if (r_refdef.view.isoverlay)
9354         {
9355                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9356                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9357                 R_TimeReport("depthclear");
9358
9359                 r_refdef.view.showdebug = false;
9360
9361                 r_waterstate.enabled = false;
9362                 r_waterstate.numwaterplanes = 0;
9363
9364                 R_RenderScene();
9365
9366                 CHECKGLERROR
9367                 return;
9368         }
9369
9370         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9371                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9372
9373         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9374
9375         R_RenderView_UpdateViewVectors();
9376
9377         R_Shadow_UpdateWorldLightSelection();
9378
9379         R_Bloom_StartFrame();
9380         R_Water_StartFrame();
9381
9382         CHECKGLERROR
9383         if (r_timereport_active)
9384                 R_TimeReport("viewsetup");
9385
9386         R_ResetViewRendering3D();
9387
9388         if (r_refdef.view.clear || r_refdef.fogenabled)
9389         {
9390                 R_ClearScreen(r_refdef.fogenabled);
9391                 if (r_timereport_active)
9392                         R_TimeReport("viewclear");
9393         }
9394         r_refdef.view.clear = true;
9395
9396         // this produces a bloom texture to be used in R_BlendView() later
9397         if (r_hdr.integer && r_bloomstate.bloomwidth)
9398         {
9399                 R_HDR_RenderBloomTexture();
9400                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9401                 r_textureframe++; // used only by R_GetCurrentTexture
9402         }
9403
9404         r_refdef.view.showdebug = true;
9405
9406         R_View_Update();
9407         if (r_timereport_active)
9408                 R_TimeReport("visibility");
9409
9410         r_waterstate.numwaterplanes = 0;
9411         if (r_waterstate.enabled)
9412                 R_RenderWaterPlanes();
9413
9414         R_RenderScene();
9415         r_waterstate.numwaterplanes = 0;
9416
9417         R_BlendView();
9418         if (r_timereport_active)
9419                 R_TimeReport("blendview");
9420
9421         GL_Scissor(0, 0, vid.width, vid.height);
9422         GL_ScissorTest(false);
9423         CHECKGLERROR
9424 }
9425
9426 void R_RenderWaterPlanes(void)
9427 {
9428         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9429         {
9430                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9431                 if (r_timereport_active)
9432                         R_TimeReport("waterworld");
9433         }
9434
9435         // don't let sound skip if going slow
9436         if (r_refdef.scene.extraupdate)
9437                 S_ExtraUpdate ();
9438
9439         R_DrawModelsAddWaterPlanes();
9440         if (r_timereport_active)
9441                 R_TimeReport("watermodels");
9442
9443         if (r_waterstate.numwaterplanes)
9444         {
9445                 R_Water_ProcessPlanes();
9446                 if (r_timereport_active)
9447                         R_TimeReport("waterscenes");
9448         }
9449 }
9450
9451 extern void R_DrawLightningBeams (void);
9452 extern void VM_CL_AddPolygonsToMeshQueue (void);
9453 extern void R_DrawPortals (void);
9454 extern cvar_t cl_locs_show;
9455 static void R_DrawLocs(void);
9456 static void R_DrawEntityBBoxes(void);
9457 static void R_DrawModelDecals(void);
9458 extern void R_DrawModelShadows(void);
9459 extern void R_DrawModelShadowMaps(void);
9460 extern cvar_t cl_decals_newsystem;
9461 extern qboolean r_shadow_usingdeferredprepass;
9462 void R_RenderScene(void)
9463 {
9464         qboolean shadowmapping = false;
9465
9466         if (r_timereport_active)
9467                 R_TimeReport("beginscene");
9468
9469         r_refdef.stats.renders++;
9470
9471         R_UpdateFogColor();
9472
9473         // don't let sound skip if going slow
9474         if (r_refdef.scene.extraupdate)
9475                 S_ExtraUpdate ();
9476
9477         R_MeshQueue_BeginScene();
9478
9479         R_SkyStartFrame();
9480
9481         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);
9482
9483         if (r_timereport_active)
9484                 R_TimeReport("skystartframe");
9485
9486         if (cl.csqc_vidvars.drawworld)
9487         {
9488                 // don't let sound skip if going slow
9489                 if (r_refdef.scene.extraupdate)
9490                         S_ExtraUpdate ();
9491
9492                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9493                 {
9494                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9495                         if (r_timereport_active)
9496                                 R_TimeReport("worldsky");
9497                 }
9498
9499                 if (R_DrawBrushModelsSky() && r_timereport_active)
9500                         R_TimeReport("bmodelsky");
9501
9502                 if (skyrendermasked && skyrenderlater)
9503                 {
9504                         // we have to force off the water clipping plane while rendering sky
9505                         R_SetupView(false);
9506                         R_Sky();
9507                         R_SetupView(true);
9508                         if (r_timereport_active)
9509                                 R_TimeReport("sky");
9510                 }
9511         }
9512
9513         R_AnimCache_CacheVisibleEntities();
9514         if (r_timereport_active)
9515                 R_TimeReport("animation");
9516
9517         R_Shadow_PrepareLights();
9518         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9519                 R_Shadow_PrepareModelShadows();
9520         if (r_timereport_active)
9521                 R_TimeReport("preparelights");
9522
9523         if (R_Shadow_ShadowMappingEnabled())
9524                 shadowmapping = true;
9525
9526         if (r_shadow_usingdeferredprepass)
9527                 R_Shadow_DrawPrepass();
9528
9529         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9530         {
9531                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9532                 if (r_timereport_active)
9533                         R_TimeReport("worlddepth");
9534         }
9535         if (r_depthfirst.integer >= 2)
9536         {
9537                 R_DrawModelsDepth();
9538                 if (r_timereport_active)
9539                         R_TimeReport("modeldepth");
9540         }
9541
9542         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9543         {
9544                 R_DrawModelShadowMaps();
9545                 R_ResetViewRendering3D();
9546                 // don't let sound skip if going slow
9547                 if (r_refdef.scene.extraupdate)
9548                         S_ExtraUpdate ();
9549         }
9550
9551         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9552         {
9553                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9554                 if (r_timereport_active)
9555                         R_TimeReport("world");
9556         }
9557
9558         // don't let sound skip if going slow
9559         if (r_refdef.scene.extraupdate)
9560                 S_ExtraUpdate ();
9561
9562         R_DrawModels();
9563         if (r_timereport_active)
9564                 R_TimeReport("models");
9565
9566         // don't let sound skip if going slow
9567         if (r_refdef.scene.extraupdate)
9568                 S_ExtraUpdate ();
9569
9570         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9571         {
9572                 R_DrawModelShadows();
9573                 R_ResetViewRendering3D();
9574                 // don't let sound skip if going slow
9575                 if (r_refdef.scene.extraupdate)
9576                         S_ExtraUpdate ();
9577         }
9578
9579         if (!r_shadow_usingdeferredprepass)
9580         {
9581                 R_Shadow_DrawLights();
9582                 if (r_timereport_active)
9583                         R_TimeReport("rtlights");
9584         }
9585
9586         // don't let sound skip if going slow
9587         if (r_refdef.scene.extraupdate)
9588                 S_ExtraUpdate ();
9589
9590         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9591         {
9592                 R_DrawModelShadows();
9593                 R_ResetViewRendering3D();
9594                 // don't let sound skip if going slow
9595                 if (r_refdef.scene.extraupdate)
9596                         S_ExtraUpdate ();
9597         }
9598
9599         if (cl.csqc_vidvars.drawworld)
9600         {
9601                 if (cl_decals_newsystem.integer)
9602                 {
9603                         R_DrawModelDecals();
9604                         if (r_timereport_active)
9605                                 R_TimeReport("modeldecals");
9606                 }
9607                 else
9608                 {
9609                         R_DrawDecals();
9610                         if (r_timereport_active)
9611                                 R_TimeReport("decals");
9612                 }
9613
9614                 R_DrawParticles();
9615                 if (r_timereport_active)
9616                         R_TimeReport("particles");
9617
9618                 R_DrawExplosions();
9619                 if (r_timereport_active)
9620                         R_TimeReport("explosions");
9621
9622                 R_DrawLightningBeams();
9623                 if (r_timereport_active)
9624                         R_TimeReport("lightning");
9625         }
9626
9627         VM_CL_AddPolygonsToMeshQueue();
9628
9629         if (r_refdef.view.showdebug)
9630         {
9631                 if (cl_locs_show.integer)
9632                 {
9633                         R_DrawLocs();
9634                         if (r_timereport_active)
9635                                 R_TimeReport("showlocs");
9636                 }
9637
9638                 if (r_drawportals.integer)
9639                 {
9640                         R_DrawPortals();
9641                         if (r_timereport_active)
9642                                 R_TimeReport("portals");
9643                 }
9644
9645                 if (r_showbboxes.value > 0)
9646                 {
9647                         R_DrawEntityBBoxes();
9648                         if (r_timereport_active)
9649                                 R_TimeReport("bboxes");
9650                 }
9651         }
9652
9653         R_MeshQueue_RenderTransparent();
9654         if (r_timereport_active)
9655                 R_TimeReport("drawtrans");
9656
9657         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))
9658         {
9659                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9660                 if (r_timereport_active)
9661                         R_TimeReport("worlddebug");
9662                 R_DrawModelsDebug();
9663                 if (r_timereport_active)
9664                         R_TimeReport("modeldebug");
9665         }
9666
9667         if (cl.csqc_vidvars.drawworld)
9668         {
9669                 R_Shadow_DrawCoronas();
9670                 if (r_timereport_active)
9671                         R_TimeReport("coronas");
9672         }
9673
9674         // don't let sound skip if going slow
9675         if (r_refdef.scene.extraupdate)
9676                 S_ExtraUpdate ();
9677
9678         R_ResetViewRendering2D();
9679 }
9680
9681 static const unsigned short bboxelements[36] =
9682 {
9683         5, 1, 3, 5, 3, 7,
9684         6, 2, 0, 6, 0, 4,
9685         7, 3, 2, 7, 2, 6,
9686         4, 0, 1, 4, 1, 5,
9687         4, 5, 7, 4, 7, 6,
9688         1, 0, 2, 1, 2, 3,
9689 };
9690
9691 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9692 {
9693         int i;
9694         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9695
9696         RSurf_ActiveWorldEntity();
9697
9698         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9699         GL_DepthMask(false);
9700         GL_DepthRange(0, 1);
9701         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9702         R_Mesh_ResetTextureState();
9703
9704         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9705         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9706         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9707         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9708         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9709         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9710         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9711         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9712         R_FillColors(color4f, 8, cr, cg, cb, ca);
9713         if (r_refdef.fogenabled)
9714         {
9715                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9716                 {
9717                         f1 = RSurf_FogVertex(v);
9718                         f2 = 1 - f1;
9719                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9720                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9721                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9722                 }
9723         }
9724         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9725         R_Mesh_ResetTextureState();
9726         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9727         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9728 }
9729
9730 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9731 {
9732         int i;
9733         float color[4];
9734         prvm_edict_t *edict;
9735         prvm_prog_t *prog_save = prog;
9736
9737         // this function draws bounding boxes of server entities
9738         if (!sv.active)
9739                 return;
9740
9741         GL_CullFace(GL_NONE);
9742         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9743
9744         prog = 0;
9745         SV_VM_Begin();
9746         for (i = 0;i < numsurfaces;i++)
9747         {
9748                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9749                 switch ((int)edict->fields.server->solid)
9750                 {
9751                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9752                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9753                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9754                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9755                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9756                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9757                 }
9758                 color[3] *= r_showbboxes.value;
9759                 color[3] = bound(0, color[3], 1);
9760                 GL_DepthTest(!r_showdisabledepthtest.integer);
9761                 GL_CullFace(r_refdef.view.cullface_front);
9762                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9763         }
9764         SV_VM_End();
9765         prog = prog_save;
9766 }
9767
9768 static void R_DrawEntityBBoxes(void)
9769 {
9770         int i;
9771         prvm_edict_t *edict;
9772         vec3_t center;
9773         prvm_prog_t *prog_save = prog;
9774
9775         // this function draws bounding boxes of server entities
9776         if (!sv.active)
9777                 return;
9778
9779         prog = 0;
9780         SV_VM_Begin();
9781         for (i = 0;i < prog->num_edicts;i++)
9782         {
9783                 edict = PRVM_EDICT_NUM(i);
9784                 if (edict->priv.server->free)
9785                         continue;
9786                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9787                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9788                         continue;
9789                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9790                         continue;
9791                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9792                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9793         }
9794         SV_VM_End();
9795         prog = prog_save;
9796 }
9797
9798 static const int nomodelelement3i[24] =
9799 {
9800         5, 2, 0,
9801         5, 1, 2,
9802         5, 0, 3,
9803         5, 3, 1,
9804         0, 2, 4,
9805         2, 1, 4,
9806         3, 0, 4,
9807         1, 3, 4
9808 };
9809
9810 static const unsigned short nomodelelement3s[24] =
9811 {
9812         5, 2, 0,
9813         5, 1, 2,
9814         5, 0, 3,
9815         5, 3, 1,
9816         0, 2, 4,
9817         2, 1, 4,
9818         3, 0, 4,
9819         1, 3, 4
9820 };
9821
9822 static const float nomodelvertex3f[6*3] =
9823 {
9824         -16,   0,   0,
9825          16,   0,   0,
9826           0, -16,   0,
9827           0,  16,   0,
9828           0,   0, -16,
9829           0,   0,  16
9830 };
9831
9832 static const float nomodelcolor4f[6*4] =
9833 {
9834         0.0f, 0.0f, 0.5f, 1.0f,
9835         0.0f, 0.0f, 0.5f, 1.0f,
9836         0.0f, 0.5f, 0.0f, 1.0f,
9837         0.0f, 0.5f, 0.0f, 1.0f,
9838         0.5f, 0.0f, 0.0f, 1.0f,
9839         0.5f, 0.0f, 0.0f, 1.0f
9840 };
9841
9842 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9843 {
9844         int i;
9845         float f1, f2, *c;
9846         float color4f[6*4];
9847
9848         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);
9849
9850         // this is only called once per entity so numsurfaces is always 1, and
9851         // surfacelist is always {0}, so this code does not handle batches
9852
9853         if (rsurface.ent_flags & RENDER_ADDITIVE)
9854         {
9855                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9856                 GL_DepthMask(false);
9857         }
9858         else if (rsurface.colormod[3] < 1)
9859         {
9860                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9861                 GL_DepthMask(false);
9862         }
9863         else
9864         {
9865                 GL_BlendFunc(GL_ONE, GL_ZERO);
9866                 GL_DepthMask(true);
9867         }
9868         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9869         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9870         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9871         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9872         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9873         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9874         for (i = 0, c = color4f;i < 6;i++, c += 4)
9875         {
9876                 c[0] *= rsurface.colormod[0];
9877                 c[1] *= rsurface.colormod[1];
9878                 c[2] *= rsurface.colormod[2];
9879                 c[3] *= rsurface.colormod[3];
9880         }
9881         if (r_refdef.fogenabled)
9882         {
9883                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9884                 {
9885                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9886                         f2 = 1 - f1;
9887                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9888                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9889                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9890                 }
9891         }
9892         R_Mesh_ResetTextureState();
9893         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9894         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9895 }
9896
9897 void R_DrawNoModel(entity_render_t *ent)
9898 {
9899         vec3_t org;
9900         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9901         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9902                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9903         else
9904                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9905 }
9906
9907 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9908 {
9909         vec3_t right1, right2, diff, normal;
9910
9911         VectorSubtract (org2, org1, normal);
9912
9913         // calculate 'right' vector for start
9914         VectorSubtract (r_refdef.view.origin, org1, diff);
9915         CrossProduct (normal, diff, right1);
9916         VectorNormalize (right1);
9917
9918         // calculate 'right' vector for end
9919         VectorSubtract (r_refdef.view.origin, org2, diff);
9920         CrossProduct (normal, diff, right2);
9921         VectorNormalize (right2);
9922
9923         vert[ 0] = org1[0] + width * right1[0];
9924         vert[ 1] = org1[1] + width * right1[1];
9925         vert[ 2] = org1[2] + width * right1[2];
9926         vert[ 3] = org1[0] - width * right1[0];
9927         vert[ 4] = org1[1] - width * right1[1];
9928         vert[ 5] = org1[2] - width * right1[2];
9929         vert[ 6] = org2[0] - width * right2[0];
9930         vert[ 7] = org2[1] - width * right2[1];
9931         vert[ 8] = org2[2] - width * right2[2];
9932         vert[ 9] = org2[0] + width * right2[0];
9933         vert[10] = org2[1] + width * right2[1];
9934         vert[11] = org2[2] + width * right2[2];
9935 }
9936
9937 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)
9938 {
9939         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9940         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9941         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9942         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9943         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9944         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9945         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9946         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9947         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9948         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9949         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9950         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9951 }
9952
9953 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9954 {
9955         int i;
9956         float *vertex3f;
9957         float v[3];
9958         VectorSet(v, x, y, z);
9959         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9960                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9961                         break;
9962         if (i == mesh->numvertices)
9963         {
9964                 if (mesh->numvertices < mesh->maxvertices)
9965                 {
9966                         VectorCopy(v, vertex3f);
9967                         mesh->numvertices++;
9968                 }
9969                 return mesh->numvertices;
9970         }
9971         else
9972                 return i;
9973 }
9974
9975 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9976 {
9977         int i;
9978         int *e, element[3];
9979         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9980         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9981         e = mesh->element3i + mesh->numtriangles * 3;
9982         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9983         {
9984                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9985                 if (mesh->numtriangles < mesh->maxtriangles)
9986                 {
9987                         *e++ = element[0];
9988                         *e++ = element[1];
9989                         *e++ = element[2];
9990                         mesh->numtriangles++;
9991                 }
9992                 element[1] = element[2];
9993         }
9994 }
9995
9996 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9997 {
9998         int i;
9999         int *e, element[3];
10000         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10001         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10002         e = mesh->element3i + mesh->numtriangles * 3;
10003         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10004         {
10005                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10006                 if (mesh->numtriangles < mesh->maxtriangles)
10007                 {
10008                         *e++ = element[0];
10009                         *e++ = element[1];
10010                         *e++ = element[2];
10011                         mesh->numtriangles++;
10012                 }
10013                 element[1] = element[2];
10014         }
10015 }
10016
10017 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10018 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10019 {
10020         int planenum, planenum2;
10021         int w;
10022         int tempnumpoints;
10023         mplane_t *plane, *plane2;
10024         double maxdist;
10025         double temppoints[2][256*3];
10026         // figure out how large a bounding box we need to properly compute this brush
10027         maxdist = 0;
10028         for (w = 0;w < numplanes;w++)
10029                 maxdist = max(maxdist, fabs(planes[w].dist));
10030         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10031         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10032         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10033         {
10034                 w = 0;
10035                 tempnumpoints = 4;
10036                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10037                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10038                 {
10039                         if (planenum2 == planenum)
10040                                 continue;
10041                         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);
10042                         w = !w;
10043                 }
10044                 if (tempnumpoints < 3)
10045                         continue;
10046                 // generate elements forming a triangle fan for this polygon
10047                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10048         }
10049 }
10050
10051 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)
10052 {
10053         texturelayer_t *layer;
10054         layer = t->currentlayers + t->currentnumlayers++;
10055         layer->type = type;
10056         layer->depthmask = depthmask;
10057         layer->blendfunc1 = blendfunc1;
10058         layer->blendfunc2 = blendfunc2;
10059         layer->texture = texture;
10060         layer->texmatrix = *matrix;
10061         layer->color[0] = r;
10062         layer->color[1] = g;
10063         layer->color[2] = b;
10064         layer->color[3] = a;
10065 }
10066
10067 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10068 {
10069         if(parms[0] == 0 && parms[1] == 0)
10070                 return false;
10071         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10072                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10073                         return false;
10074         return true;
10075 }
10076
10077 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10078 {
10079         double index, f;
10080         index = parms[2] + r_refdef.scene.time * parms[3];
10081         index -= floor(index);
10082         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10083         {
10084         default:
10085         case Q3WAVEFUNC_NONE:
10086         case Q3WAVEFUNC_NOISE:
10087         case Q3WAVEFUNC_COUNT:
10088                 f = 0;
10089                 break;
10090         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10091         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10092         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10093         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10094         case Q3WAVEFUNC_TRIANGLE:
10095                 index *= 4;
10096                 f = index - floor(index);
10097                 if (index < 1)
10098                         f = f;
10099                 else if (index < 2)
10100                         f = 1 - f;
10101                 else if (index < 3)
10102                         f = -f;
10103                 else
10104                         f = -(1 - f);
10105                 break;
10106         }
10107         f = parms[0] + parms[1] * f;
10108         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10109                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10110         return (float) f;
10111 }
10112
10113 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10114 {
10115         int w, h, idx;
10116         float f;
10117         float tcmat[12];
10118         matrix4x4_t matrix, temp;
10119         switch(tcmod->tcmod)
10120         {
10121                 case Q3TCMOD_COUNT:
10122                 case Q3TCMOD_NONE:
10123                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10124                                 matrix = r_waterscrollmatrix;
10125                         else
10126                                 matrix = identitymatrix;
10127                         break;
10128                 case Q3TCMOD_ENTITYTRANSLATE:
10129                         // this is used in Q3 to allow the gamecode to control texcoord
10130                         // scrolling on the entity, which is not supported in darkplaces yet.
10131                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10132                         break;
10133                 case Q3TCMOD_ROTATE:
10134                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10135                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10136                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10137                         break;
10138                 case Q3TCMOD_SCALE:
10139                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10140                         break;
10141                 case Q3TCMOD_SCROLL:
10142                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10143                         break;
10144                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10145                         w = (int) tcmod->parms[0];
10146                         h = (int) tcmod->parms[1];
10147                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10148                         f = f - floor(f);
10149                         idx = (int) floor(f * w * h);
10150                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10151                         break;
10152                 case Q3TCMOD_STRETCH:
10153                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10154                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10155                         break;
10156                 case Q3TCMOD_TRANSFORM:
10157                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10158                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10159                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10160                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10161                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10162                         break;
10163                 case Q3TCMOD_TURBULENT:
10164                         // this is handled in the RSurf_PrepareVertices function
10165                         matrix = identitymatrix;
10166                         break;
10167         }
10168         temp = *texmatrix;
10169         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10170 }
10171
10172 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10173 {
10174         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10175         char name[MAX_QPATH];
10176         skinframe_t *skinframe;
10177         unsigned char pixels[296*194];
10178         strlcpy(cache->name, skinname, sizeof(cache->name));
10179         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10180         if (developer_loading.integer)
10181                 Con_Printf("loading %s\n", name);
10182         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10183         if (!skinframe || !skinframe->base)
10184         {
10185                 unsigned char *f;
10186                 fs_offset_t filesize;
10187                 skinframe = NULL;
10188                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10189                 if (f)
10190                 {
10191                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10192                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10193                         Mem_Free(f);
10194                 }
10195         }
10196         cache->skinframe = skinframe;
10197 }
10198
10199 texture_t *R_GetCurrentTexture(texture_t *t)
10200 {
10201         int i;
10202         const entity_render_t *ent = rsurface.entity;
10203         dp_model_t *model = ent->model;
10204         q3shaderinfo_layer_tcmod_t *tcmod;
10205
10206         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10207                 return t->currentframe;
10208         t->update_lastrenderframe = r_textureframe;
10209         t->update_lastrenderentity = (void *)ent;
10210
10211         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10212                 t->camera_entity = ent->entitynumber;
10213         else
10214                 t->camera_entity = 0;
10215
10216         // switch to an alternate material if this is a q1bsp animated material
10217         {
10218                 texture_t *texture = t;
10219                 int s = rsurface.ent_skinnum;
10220                 if ((unsigned int)s >= (unsigned int)model->numskins)
10221                         s = 0;
10222                 if (model->skinscenes)
10223                 {
10224                         if (model->skinscenes[s].framecount > 1)
10225                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10226                         else
10227                                 s = model->skinscenes[s].firstframe;
10228                 }
10229                 if (s > 0)
10230                         t = t + s * model->num_surfaces;
10231                 if (t->animated)
10232                 {
10233                         // use an alternate animation if the entity's frame is not 0,
10234                         // and only if the texture has an alternate animation
10235                         if (rsurface.ent_alttextures && t->anim_total[1])
10236                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10237                         else
10238                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10239                 }
10240                 texture->currentframe = t;
10241         }
10242
10243         // update currentskinframe to be a qw skin or animation frame
10244         if (rsurface.ent_qwskin >= 0)
10245         {
10246                 i = rsurface.ent_qwskin;
10247                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10248                 {
10249                         r_qwskincache_size = cl.maxclients;
10250                         if (r_qwskincache)
10251                                 Mem_Free(r_qwskincache);
10252                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10253                 }
10254                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10255                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10256                 t->currentskinframe = r_qwskincache[i].skinframe;
10257                 if (t->currentskinframe == NULL)
10258                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10259         }
10260         else if (t->numskinframes >= 2)
10261                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10262         if (t->backgroundnumskinframes >= 2)
10263                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10264
10265         t->currentmaterialflags = t->basematerialflags;
10266         t->currentalpha = rsurface.colormod[3];
10267         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10268                 t->currentalpha *= r_wateralpha.value;
10269         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10270                 t->currentalpha *= t->r_water_wateralpha;
10271         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10272                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10273         if (!(rsurface.ent_flags & RENDER_LIGHT))
10274                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10275         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10276         {
10277                 // pick a model lighting mode
10278                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10279                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10280                 else
10281                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10282         }
10283         if (rsurface.ent_flags & RENDER_ADDITIVE)
10284                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10285         else if (t->currentalpha < 1)
10286                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10287         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10288                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10289         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10290                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10291         if (t->backgroundnumskinframes)
10292                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10293         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10294         {
10295                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10296                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10297         }
10298         else
10299                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10300         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10301                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10302
10303         // there is no tcmod
10304         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10305         {
10306                 t->currenttexmatrix = r_waterscrollmatrix;
10307                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10308         }
10309         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10310         {
10311                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10312                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10313         }
10314
10315         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10316                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10317         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10318                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10319
10320         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10321         if (t->currentskinframe->qpixels)
10322                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10323         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10324         if (!t->basetexture)
10325                 t->basetexture = r_texture_notexture;
10326         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10327         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10328         t->nmaptexture = t->currentskinframe->nmap;
10329         if (!t->nmaptexture)
10330                 t->nmaptexture = r_texture_blanknormalmap;
10331         t->glosstexture = r_texture_black;
10332         t->glowtexture = t->currentskinframe->glow;
10333         t->fogtexture = t->currentskinframe->fog;
10334         t->reflectmasktexture = t->currentskinframe->reflect;
10335         if (t->backgroundnumskinframes)
10336         {
10337                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10338                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10339                 t->backgroundglosstexture = r_texture_black;
10340                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10341                 if (!t->backgroundnmaptexture)
10342                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10343         }
10344         else
10345         {
10346                 t->backgroundbasetexture = r_texture_white;
10347                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10348                 t->backgroundglosstexture = r_texture_black;
10349                 t->backgroundglowtexture = NULL;
10350         }
10351         t->specularpower = r_shadow_glossexponent.value;
10352         // TODO: store reference values for these in the texture?
10353         t->specularscale = 0;
10354         if (r_shadow_gloss.integer > 0)
10355         {
10356                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10357                 {
10358                         if (r_shadow_glossintensity.value > 0)
10359                         {
10360                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10361                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10362                                 t->specularscale = r_shadow_glossintensity.value;
10363                         }
10364                 }
10365                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10366                 {
10367                         t->glosstexture = r_texture_white;
10368                         t->backgroundglosstexture = r_texture_white;
10369                         t->specularscale = r_shadow_gloss2intensity.value;
10370                         t->specularpower = r_shadow_gloss2exponent.value;
10371                 }
10372         }
10373         t->specularscale *= t->specularscalemod;
10374         t->specularpower *= t->specularpowermod;
10375
10376         // lightmaps mode looks bad with dlights using actual texturing, so turn
10377         // off the colormap and glossmap, but leave the normalmap on as it still
10378         // accurately represents the shading involved
10379         if (gl_lightmaps.integer)
10380         {
10381                 t->basetexture = r_texture_grey128;
10382                 t->pantstexture = r_texture_black;
10383                 t->shirttexture = r_texture_black;
10384                 t->nmaptexture = r_texture_blanknormalmap;
10385                 t->glosstexture = r_texture_black;
10386                 t->glowtexture = NULL;
10387                 t->fogtexture = NULL;
10388                 t->reflectmasktexture = NULL;
10389                 t->backgroundbasetexture = NULL;
10390                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10391                 t->backgroundglosstexture = r_texture_black;
10392                 t->backgroundglowtexture = NULL;
10393                 t->specularscale = 0;
10394                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10395         }
10396
10397         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10398         VectorClear(t->dlightcolor);
10399         t->currentnumlayers = 0;
10400         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10401         {
10402                 int blendfunc1, blendfunc2;
10403                 qboolean depthmask;
10404                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10405                 {
10406                         blendfunc1 = GL_SRC_ALPHA;
10407                         blendfunc2 = GL_ONE;
10408                 }
10409                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10410                 {
10411                         blendfunc1 = GL_SRC_ALPHA;
10412                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10413                 }
10414                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10415                 {
10416                         blendfunc1 = t->customblendfunc[0];
10417                         blendfunc2 = t->customblendfunc[1];
10418                 }
10419                 else
10420                 {
10421                         blendfunc1 = GL_ONE;
10422                         blendfunc2 = GL_ZERO;
10423                 }
10424                 // don't colormod evilblend textures
10425                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10426                         VectorSet(t->lightmapcolor, 1, 1, 1);
10427                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10428                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10429                 {
10430                         // fullbright is not affected by r_refdef.lightmapintensity
10431                         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]);
10432                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10433                                 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]);
10434                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10435                                 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]);
10436                 }
10437                 else
10438                 {
10439                         vec3_t ambientcolor;
10440                         float colorscale;
10441                         // set the color tint used for lights affecting this surface
10442                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10443                         colorscale = 2;
10444                         // q3bsp has no lightmap updates, so the lightstylevalue that
10445                         // would normally be baked into the lightmap must be
10446                         // applied to the color
10447                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10448                         if (model->type == mod_brushq3)
10449                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10450                         colorscale *= r_refdef.lightmapintensity;
10451                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10452                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10453                         // basic lit geometry
10454                         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]);
10455                         // add pants/shirt if needed
10456                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10457                                 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]);
10458                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10459                                 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]);
10460                         // now add ambient passes if needed
10461                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10462                         {
10463                                 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]);
10464                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10465                                         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]);
10466                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10467                                         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]);
10468                         }
10469                 }
10470                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10471                         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]);
10472                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10473                 {
10474                         // if this is opaque use alpha blend which will darken the earlier
10475                         // passes cheaply.
10476                         //
10477                         // if this is an alpha blended material, all the earlier passes
10478                         // were darkened by fog already, so we only need to add the fog
10479                         // color ontop through the fog mask texture
10480                         //
10481                         // if this is an additive blended material, all the earlier passes
10482                         // were darkened by fog already, and we should not add fog color
10483                         // (because the background was not darkened, there is no fog color
10484                         // that was lost behind it).
10485                         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]);
10486                 }
10487         }
10488
10489         return t->currentframe;
10490 }
10491
10492 rsurfacestate_t rsurface;
10493
10494 void R_Mesh_ResizeArrays(int newvertices)
10495 {
10496         unsigned char *base;
10497         size_t size;
10498         if (rsurface.array_size >= newvertices)
10499                 return;
10500         if (rsurface.array_base)
10501                 Mem_Free(rsurface.array_base);
10502         rsurface.array_size = (newvertices + 1023) & ~1023;
10503         size = 0;
10504         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10505         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10506         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10507         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10508         size += rsurface.array_size * sizeof(float[3]);
10509         size += rsurface.array_size * sizeof(float[3]);
10510         size += rsurface.array_size * sizeof(float[3]);
10511         size += rsurface.array_size * sizeof(float[3]);
10512         size += rsurface.array_size * sizeof(float[3]);
10513         size += rsurface.array_size * sizeof(float[3]);
10514         size += rsurface.array_size * sizeof(float[3]);
10515         size += rsurface.array_size * sizeof(float[3]);
10516         size += rsurface.array_size * sizeof(float[4]);
10517         size += rsurface.array_size * sizeof(float[2]);
10518         size += rsurface.array_size * sizeof(float[2]);
10519         size += rsurface.array_size * sizeof(float[4]);
10520         size += rsurface.array_size * sizeof(int[3]);
10521         size += rsurface.array_size * sizeof(unsigned short[3]);
10522         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10523         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10524         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10525         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10526         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10527         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10528         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10529         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10530         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10531         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10532         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10533         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10534         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10535         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10536         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10537         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10538         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10539         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10540         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10541 }
10542
10543 void RSurf_ActiveWorldEntity(void)
10544 {
10545         dp_model_t *model = r_refdef.scene.worldmodel;
10546         //if (rsurface.entity == r_refdef.scene.worldentity)
10547         //      return;
10548         rsurface.entity = r_refdef.scene.worldentity;
10549         rsurface.skeleton = NULL;
10550         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10551         rsurface.ent_skinnum = 0;
10552         rsurface.ent_qwskin = -1;
10553         rsurface.ent_shadertime = 0;
10554         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10555         if (rsurface.array_size < model->surfmesh.num_vertices)
10556                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10557         rsurface.matrix = identitymatrix;
10558         rsurface.inversematrix = identitymatrix;
10559         rsurface.matrixscale = 1;
10560         rsurface.inversematrixscale = 1;
10561         R_EntityMatrix(&identitymatrix);
10562         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10563         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10564         rsurface.fograngerecip = r_refdef.fograngerecip;
10565         rsurface.fogheightfade = r_refdef.fogheightfade;
10566         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10567         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10568         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10569         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10570         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10571         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10572         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10573         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10574         rsurface.colormod[3] = 1;
10575         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);
10576         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10577         rsurface.frameblend[0].lerp = 1;
10578         rsurface.ent_alttextures = false;
10579         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10580         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10581         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10582         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10583         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10584         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10585         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10586         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10587         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10588         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10589         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10590         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10591         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10592         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10593         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10594         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10595         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10596         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10597         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10598         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10599         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10600         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10601         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10602         rsurface.modelelement3i = model->surfmesh.data_element3i;
10603         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10604         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10605         rsurface.modelelement3s = model->surfmesh.data_element3s;
10606         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10607         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10608         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10609         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10610         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10611         rsurface.modelsurfaces = model->data_surfaces;
10612         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10613         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10614         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10615         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10616         rsurface.modelgeneratedvertex = false;
10617         rsurface.batchgeneratedvertex = false;
10618         rsurface.batchfirstvertex = 0;
10619         rsurface.batchnumvertices = 0;
10620         rsurface.batchfirsttriangle = 0;
10621         rsurface.batchnumtriangles = 0;
10622         rsurface.batchvertex3f  = NULL;
10623         rsurface.batchvertex3f_vertexbuffer = NULL;
10624         rsurface.batchvertex3f_bufferoffset = 0;
10625         rsurface.batchsvector3f = NULL;
10626         rsurface.batchsvector3f_vertexbuffer = NULL;
10627         rsurface.batchsvector3f_bufferoffset = 0;
10628         rsurface.batchtvector3f = NULL;
10629         rsurface.batchtvector3f_vertexbuffer = NULL;
10630         rsurface.batchtvector3f_bufferoffset = 0;
10631         rsurface.batchnormal3f  = NULL;
10632         rsurface.batchnormal3f_vertexbuffer = NULL;
10633         rsurface.batchnormal3f_bufferoffset = 0;
10634         rsurface.batchlightmapcolor4f = NULL;
10635         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10636         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10637         rsurface.batchtexcoordtexture2f = NULL;
10638         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10639         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10640         rsurface.batchtexcoordlightmap2f = NULL;
10641         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10642         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10643         rsurface.batchvertexmesh = NULL;
10644         rsurface.batchvertexmeshbuffer = NULL;
10645         rsurface.batchvertexposition = NULL;
10646         rsurface.batchvertexpositionbuffer = NULL;
10647         rsurface.batchelement3i = NULL;
10648         rsurface.batchelement3i_indexbuffer = NULL;
10649         rsurface.batchelement3i_bufferoffset = 0;
10650         rsurface.batchelement3s = NULL;
10651         rsurface.batchelement3s_indexbuffer = NULL;
10652         rsurface.batchelement3s_bufferoffset = 0;
10653         rsurface.passcolor4f = NULL;
10654         rsurface.passcolor4f_vertexbuffer = NULL;
10655         rsurface.passcolor4f_bufferoffset = 0;
10656 }
10657
10658 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10659 {
10660         dp_model_t *model = ent->model;
10661         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10662         //      return;
10663         rsurface.entity = (entity_render_t *)ent;
10664         rsurface.skeleton = ent->skeleton;
10665         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10666         rsurface.ent_skinnum = ent->skinnum;
10667         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;
10668         rsurface.ent_shadertime = ent->shadertime;
10669         rsurface.ent_flags = ent->flags;
10670         if (rsurface.array_size < model->surfmesh.num_vertices)
10671                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10672         rsurface.matrix = ent->matrix;
10673         rsurface.inversematrix = ent->inversematrix;
10674         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10675         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10676         R_EntityMatrix(&rsurface.matrix);
10677         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10678         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10679         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10680         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10681         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10682         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10683         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10684         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10685         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10686         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10687         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10688         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10689         rsurface.colormod[3] = ent->alpha;
10690         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10691         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10692         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10693         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10694         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10695         if (ent->model->brush.submodel && !prepass)
10696         {
10697                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10698                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10699         }
10700         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10701         {
10702                 if (ent->animcache_vertex3f && !r_framedata_failed)
10703                 {
10704                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10705                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10706                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10707                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10708                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10709                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10710                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10711                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10712                 }
10713                 else if (wanttangents)
10714                 {
10715                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10716                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10717                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10718                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10719                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10720                         rsurface.modelvertexmesh = NULL;
10721                         rsurface.modelvertexmeshbuffer = NULL;
10722                         rsurface.modelvertexposition = NULL;
10723                         rsurface.modelvertexpositionbuffer = NULL;
10724                 }
10725                 else if (wantnormals)
10726                 {
10727                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10728                         rsurface.modelsvector3f = NULL;
10729                         rsurface.modeltvector3f = NULL;
10730                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10731                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10732                         rsurface.modelvertexmesh = NULL;
10733                         rsurface.modelvertexmeshbuffer = NULL;
10734                         rsurface.modelvertexposition = NULL;
10735                         rsurface.modelvertexpositionbuffer = NULL;
10736                 }
10737                 else
10738                 {
10739                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10740                         rsurface.modelsvector3f = NULL;
10741                         rsurface.modeltvector3f = NULL;
10742                         rsurface.modelnormal3f = NULL;
10743                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10744                         rsurface.modelvertexmesh = NULL;
10745                         rsurface.modelvertexmeshbuffer = NULL;
10746                         rsurface.modelvertexposition = NULL;
10747                         rsurface.modelvertexpositionbuffer = NULL;
10748                 }
10749                 rsurface.modelvertex3f_vertexbuffer = 0;
10750                 rsurface.modelvertex3f_bufferoffset = 0;
10751                 rsurface.modelsvector3f_vertexbuffer = 0;
10752                 rsurface.modelsvector3f_bufferoffset = 0;
10753                 rsurface.modeltvector3f_vertexbuffer = 0;
10754                 rsurface.modeltvector3f_bufferoffset = 0;
10755                 rsurface.modelnormal3f_vertexbuffer = 0;
10756                 rsurface.modelnormal3f_bufferoffset = 0;
10757                 rsurface.modelgeneratedvertex = true;
10758         }
10759         else
10760         {
10761                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10762                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10763                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10764                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10765                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10766                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10767                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10768                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10769                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10770                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10771                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10772                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10773                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10774                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10775                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10776                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10777                 rsurface.modelgeneratedvertex = false;
10778         }
10779         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10780         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10781         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10782         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10783         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10784         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10785         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10786         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10787         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10788         rsurface.modelelement3i = model->surfmesh.data_element3i;
10789         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10790         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10791         rsurface.modelelement3s = model->surfmesh.data_element3s;
10792         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10793         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10794         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10795         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10796         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10797         rsurface.modelsurfaces = model->data_surfaces;
10798         rsurface.batchgeneratedvertex = false;
10799         rsurface.batchfirstvertex = 0;
10800         rsurface.batchnumvertices = 0;
10801         rsurface.batchfirsttriangle = 0;
10802         rsurface.batchnumtriangles = 0;
10803         rsurface.batchvertex3f  = NULL;
10804         rsurface.batchvertex3f_vertexbuffer = NULL;
10805         rsurface.batchvertex3f_bufferoffset = 0;
10806         rsurface.batchsvector3f = NULL;
10807         rsurface.batchsvector3f_vertexbuffer = NULL;
10808         rsurface.batchsvector3f_bufferoffset = 0;
10809         rsurface.batchtvector3f = NULL;
10810         rsurface.batchtvector3f_vertexbuffer = NULL;
10811         rsurface.batchtvector3f_bufferoffset = 0;
10812         rsurface.batchnormal3f  = NULL;
10813         rsurface.batchnormal3f_vertexbuffer = NULL;
10814         rsurface.batchnormal3f_bufferoffset = 0;
10815         rsurface.batchlightmapcolor4f = NULL;
10816         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10817         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10818         rsurface.batchtexcoordtexture2f = NULL;
10819         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10820         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10821         rsurface.batchtexcoordlightmap2f = NULL;
10822         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10823         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10824         rsurface.batchvertexmesh = NULL;
10825         rsurface.batchvertexmeshbuffer = NULL;
10826         rsurface.batchvertexposition = NULL;
10827         rsurface.batchvertexpositionbuffer = NULL;
10828         rsurface.batchelement3i = NULL;
10829         rsurface.batchelement3i_indexbuffer = NULL;
10830         rsurface.batchelement3i_bufferoffset = 0;
10831         rsurface.batchelement3s = NULL;
10832         rsurface.batchelement3s_indexbuffer = NULL;
10833         rsurface.batchelement3s_bufferoffset = 0;
10834         rsurface.passcolor4f = NULL;
10835         rsurface.passcolor4f_vertexbuffer = NULL;
10836         rsurface.passcolor4f_bufferoffset = 0;
10837 }
10838
10839 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)
10840 {
10841         int i;
10842
10843         rsurface.entity = r_refdef.scene.worldentity;
10844         rsurface.skeleton = NULL;
10845         rsurface.ent_skinnum = 0;
10846         rsurface.ent_qwskin = -1;
10847         rsurface.ent_shadertime = shadertime;
10848         rsurface.ent_flags = entflags;
10849         rsurface.modelnumvertices = numvertices;
10850         rsurface.modelnumtriangles = numtriangles;
10851         if (rsurface.array_size < rsurface.modelnumvertices)
10852                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10853         rsurface.matrix = *matrix;
10854         rsurface.inversematrix = *inversematrix;
10855         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10856         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10857         R_EntityMatrix(&rsurface.matrix);
10858         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10859         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10860         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10861         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10862         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10863         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10864         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10865         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10866         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10867         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10868         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10869         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10870         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);
10871         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10872         rsurface.frameblend[0].lerp = 1;
10873         rsurface.ent_alttextures = false;
10874         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10875         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10876         if (wanttangents)
10877         {
10878                 rsurface.modelvertex3f = vertex3f;
10879                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10880                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10881                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10882         }
10883         else if (wantnormals)
10884         {
10885                 rsurface.modelvertex3f = vertex3f;
10886                 rsurface.modelsvector3f = NULL;
10887                 rsurface.modeltvector3f = NULL;
10888                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10889         }
10890         else
10891         {
10892                 rsurface.modelvertex3f = vertex3f;
10893                 rsurface.modelsvector3f = NULL;
10894                 rsurface.modeltvector3f = NULL;
10895                 rsurface.modelnormal3f = NULL;
10896         }
10897         rsurface.modelvertexmesh = NULL;
10898         rsurface.modelvertexmeshbuffer = NULL;
10899         rsurface.modelvertexposition = NULL;
10900         rsurface.modelvertexpositionbuffer = NULL;
10901         rsurface.modelvertex3f_vertexbuffer = 0;
10902         rsurface.modelvertex3f_bufferoffset = 0;
10903         rsurface.modelsvector3f_vertexbuffer = 0;
10904         rsurface.modelsvector3f_bufferoffset = 0;
10905         rsurface.modeltvector3f_vertexbuffer = 0;
10906         rsurface.modeltvector3f_bufferoffset = 0;
10907         rsurface.modelnormal3f_vertexbuffer = 0;
10908         rsurface.modelnormal3f_bufferoffset = 0;
10909         rsurface.modelgeneratedvertex = true;
10910         rsurface.modellightmapcolor4f  = color4f;
10911         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10912         rsurface.modellightmapcolor4f_bufferoffset = 0;
10913         rsurface.modeltexcoordtexture2f  = texcoord2f;
10914         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10915         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10916         rsurface.modeltexcoordlightmap2f  = NULL;
10917         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10918         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10919         rsurface.modelelement3i = element3i;
10920         rsurface.modelelement3i_indexbuffer = NULL;
10921         rsurface.modelelement3i_bufferoffset = 0;
10922         rsurface.modelelement3s = element3s;
10923         rsurface.modelelement3s_indexbuffer = NULL;
10924         rsurface.modelelement3s_bufferoffset = 0;
10925         rsurface.modellightmapoffsets = NULL;
10926         rsurface.modelsurfaces = NULL;
10927         rsurface.batchgeneratedvertex = false;
10928         rsurface.batchfirstvertex = 0;
10929         rsurface.batchnumvertices = 0;
10930         rsurface.batchfirsttriangle = 0;
10931         rsurface.batchnumtriangles = 0;
10932         rsurface.batchvertex3f  = NULL;
10933         rsurface.batchvertex3f_vertexbuffer = NULL;
10934         rsurface.batchvertex3f_bufferoffset = 0;
10935         rsurface.batchsvector3f = NULL;
10936         rsurface.batchsvector3f_vertexbuffer = NULL;
10937         rsurface.batchsvector3f_bufferoffset = 0;
10938         rsurface.batchtvector3f = NULL;
10939         rsurface.batchtvector3f_vertexbuffer = NULL;
10940         rsurface.batchtvector3f_bufferoffset = 0;
10941         rsurface.batchnormal3f  = NULL;
10942         rsurface.batchnormal3f_vertexbuffer = NULL;
10943         rsurface.batchnormal3f_bufferoffset = 0;
10944         rsurface.batchlightmapcolor4f = NULL;
10945         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10946         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10947         rsurface.batchtexcoordtexture2f = NULL;
10948         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10949         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10950         rsurface.batchtexcoordlightmap2f = NULL;
10951         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10952         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10953         rsurface.batchvertexmesh = NULL;
10954         rsurface.batchvertexmeshbuffer = NULL;
10955         rsurface.batchvertexposition = NULL;
10956         rsurface.batchvertexpositionbuffer = NULL;
10957         rsurface.batchelement3i = NULL;
10958         rsurface.batchelement3i_indexbuffer = NULL;
10959         rsurface.batchelement3i_bufferoffset = 0;
10960         rsurface.batchelement3s = NULL;
10961         rsurface.batchelement3s_indexbuffer = NULL;
10962         rsurface.batchelement3s_bufferoffset = 0;
10963         rsurface.passcolor4f = NULL;
10964         rsurface.passcolor4f_vertexbuffer = NULL;
10965         rsurface.passcolor4f_bufferoffset = 0;
10966
10967         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10968         {
10969                 if ((wantnormals || wanttangents) && !normal3f)
10970                 {
10971                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10972                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10973                 }
10974                 if (wanttangents && !svector3f)
10975                 {
10976                         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);
10977                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10978                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10979                 }
10980         }
10981
10982         // now convert arrays into vertexmesh structs
10983         for (i = 0;i < numvertices;i++)
10984         {
10985                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10986                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10987                 if (rsurface.modelsvector3f)
10988                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10989                 if (rsurface.modeltvector3f)
10990                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10991                 if (rsurface.modelnormal3f)
10992                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10993                 if (rsurface.modellightmapcolor4f)
10994                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10995                 if (rsurface.modeltexcoordtexture2f)
10996                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10997                 if (rsurface.modeltexcoordlightmap2f)
10998                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10999         }
11000 }
11001
11002 float RSurf_FogPoint(const float *v)
11003 {
11004         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11005         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11006         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11007         float FogHeightFade = r_refdef.fogheightfade;
11008         float fogfrac;
11009         unsigned int fogmasktableindex;
11010         if (r_refdef.fogplaneviewabove)
11011                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11012         else
11013                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11014         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11015         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11016 }
11017
11018 float RSurf_FogVertex(const float *v)
11019 {
11020         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11021         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11022         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11023         float FogHeightFade = rsurface.fogheightfade;
11024         float fogfrac;
11025         unsigned int fogmasktableindex;
11026         if (r_refdef.fogplaneviewabove)
11027                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11028         else
11029                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11030         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11031         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11032 }
11033
11034 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11035 {
11036         int i;
11037         for (i = 0;i < numelements;i++)
11038                 outelement3i[i] = inelement3i[i] + adjust;
11039 }
11040
11041 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11042 extern cvar_t gl_vbo;
11043 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11044 {
11045         int deformindex;
11046         int firsttriangle;
11047         int numtriangles;
11048         int firstvertex;
11049         int endvertex;
11050         int numvertices;
11051         int surfacefirsttriangle;
11052         int surfacenumtriangles;
11053         int surfacefirstvertex;
11054         int surfaceendvertex;
11055         int surfacenumvertices;
11056         int needsupdate;
11057         int i, j;
11058         qboolean gaps;
11059         qboolean dynamicvertex;
11060         float amplitude;
11061         float animpos;
11062         float scale;
11063         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11064         float waveparms[4];
11065         q3shaderinfo_deform_t *deform;
11066         const msurface_t *surface, *firstsurface;
11067         r_vertexposition_t *vertexposition;
11068         r_vertexmesh_t *vertexmesh;
11069         if (!texturenumsurfaces)
11070                 return;
11071         // find vertex range of this surface batch
11072         gaps = false;
11073         firstsurface = texturesurfacelist[0];
11074         firsttriangle = firstsurface->num_firsttriangle;
11075         numtriangles = 0;
11076         firstvertex = endvertex = firstsurface->num_firstvertex;
11077         for (i = 0;i < texturenumsurfaces;i++)
11078         {
11079                 surface = texturesurfacelist[i];
11080                 if (surface != firstsurface + i)
11081                         gaps = true;
11082                 surfacefirstvertex = surface->num_firstvertex;
11083                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11084                 surfacenumtriangles = surface->num_triangles;
11085                 if (firstvertex > surfacefirstvertex)
11086                         firstvertex = surfacefirstvertex;
11087                 if (endvertex < surfaceendvertex)
11088                         endvertex = surfaceendvertex;
11089                 numtriangles += surfacenumtriangles;
11090         }
11091         if (!numtriangles)
11092                 return;
11093
11094         // we now know the vertex range used, and if there are any gaps in it
11095         rsurface.batchfirstvertex = firstvertex;
11096         rsurface.batchnumvertices = endvertex - firstvertex;
11097         rsurface.batchfirsttriangle = firsttriangle;
11098         rsurface.batchnumtriangles = numtriangles;
11099
11100         // this variable holds flags for which properties have been updated that
11101         // may require regenerating vertexmesh or vertexposition arrays...
11102         needsupdate = 0;
11103
11104         // check if any dynamic vertex processing must occur
11105         dynamicvertex = false;
11106
11107         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11108                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11109         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11110         {
11111                 switch (deform->deform)
11112                 {
11113                 default:
11114                 case Q3DEFORM_PROJECTIONSHADOW:
11115                 case Q3DEFORM_TEXT0:
11116                 case Q3DEFORM_TEXT1:
11117                 case Q3DEFORM_TEXT2:
11118                 case Q3DEFORM_TEXT3:
11119                 case Q3DEFORM_TEXT4:
11120                 case Q3DEFORM_TEXT5:
11121                 case Q3DEFORM_TEXT6:
11122                 case Q3DEFORM_TEXT7:
11123                 case Q3DEFORM_NONE:
11124                         break;
11125                 case Q3DEFORM_AUTOSPRITE:
11126                         dynamicvertex = true;
11127                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11128                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11129                         break;
11130                 case Q3DEFORM_AUTOSPRITE2:
11131                         dynamicvertex = true;
11132                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11133                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11134                         break;
11135                 case Q3DEFORM_NORMAL:
11136                         dynamicvertex = true;
11137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11138                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11139                         break;
11140                 case Q3DEFORM_WAVE:
11141                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11142                                 break; // if wavefunc is a nop, ignore this transform
11143                         dynamicvertex = true;
11144                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11145                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11146                         break;
11147                 case Q3DEFORM_BULGE:
11148                         dynamicvertex = true;
11149                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11150                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11151                         break;
11152                 case Q3DEFORM_MOVE:
11153                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11154                                 break; // if wavefunc is a nop, ignore this transform
11155                         dynamicvertex = true;
11156                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11157                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11158                         break;
11159                 }
11160         }
11161         switch(rsurface.texture->tcgen.tcgen)
11162         {
11163         default:
11164         case Q3TCGEN_TEXTURE:
11165                 break;
11166         case Q3TCGEN_LIGHTMAP:
11167                 dynamicvertex = true;
11168                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11169                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11170                 break;
11171         case Q3TCGEN_VECTOR:
11172                 dynamicvertex = true;
11173                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11174                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11175                 break;
11176         case Q3TCGEN_ENVIRONMENT:
11177                 dynamicvertex = true;
11178                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11179                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11180                 break;
11181         }
11182         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11183         {
11184                 dynamicvertex = true;
11185                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11186                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11187         }
11188
11189         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11190         {
11191                 dynamicvertex = true;
11192                 batchneed |= BATCHNEED_NOGAPS;
11193                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11194         }
11195
11196         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11197         {
11198                 dynamicvertex = true;
11199                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11200                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11201         }
11202
11203         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11204         {
11205                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11206                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11207                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11208                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11209                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11210                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11211                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11212         }
11213
11214         // when the model data has no vertex buffer (dynamic mesh), we need to
11215         // eliminate gaps
11216         if (!rsurface.modelvertexmeshbuffer)
11217                 batchneed |= BATCHNEED_NOGAPS;
11218
11219         // if needsupdate, we have to do a dynamic vertex batch for sure
11220         if (needsupdate & batchneed)
11221                 dynamicvertex = true;
11222
11223         // see if we need to build vertexmesh from arrays
11224         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11225                 dynamicvertex = true;
11226
11227         // see if we need to build vertexposition from arrays
11228         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11229                 dynamicvertex = true;
11230
11231         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11232         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11233                 dynamicvertex = true;
11234
11235         // if there is a chance of animated vertex colors, it's a dynamic batch
11236         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11237                 dynamicvertex = true;
11238
11239         rsurface.batchvertex3f = rsurface.modelvertex3f;
11240         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11241         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11242         rsurface.batchsvector3f = rsurface.modelsvector3f;
11243         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11244         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11245         rsurface.batchtvector3f = rsurface.modeltvector3f;
11246         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11247         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11248         rsurface.batchnormal3f = rsurface.modelnormal3f;
11249         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11250         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11251         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11252         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11253         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11254         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11255         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11256         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11257         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11258         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11259         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11260         rsurface.batchvertexposition = rsurface.modelvertexposition;
11261         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11262         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11263         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11264         rsurface.batchelement3i = rsurface.modelelement3i;
11265         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11266         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11267         rsurface.batchelement3s = rsurface.modelelement3s;
11268         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11269         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11270
11271         // if any dynamic vertex processing has to occur in software, we copy the
11272         // entire surface list together before processing to rebase the vertices
11273         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11274         //
11275         // if any gaps exist and we do not have a static vertex buffer, we have to
11276         // copy the surface list together to avoid wasting upload bandwidth on the
11277         // vertices in the gaps.
11278         //
11279         // if gaps exist and we have a static vertex buffer, we still have to
11280         // combine the index buffer ranges into one dynamic index buffer.
11281         //
11282         // in all cases we end up with data that can be drawn in one call.
11283
11284         if (!dynamicvertex)
11285         {
11286                 // static vertex data, just set pointers...
11287                 rsurface.batchgeneratedvertex = false;
11288                 // if there are gaps, we want to build a combined index buffer,
11289                 // otherwise use the original static buffer with an appropriate offset
11290                 if (gaps)
11291                 {
11292                         firsttriangle = 0;
11293                         numtriangles = 0;
11294                         for (i = 0;i < texturenumsurfaces;i++)
11295                         {
11296                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11297                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11298                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11299                                 numtriangles += surfacenumtriangles;
11300                         }
11301                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11302                         rsurface.batchelement3i_indexbuffer = NULL;
11303                         rsurface.batchelement3i_bufferoffset = 0;
11304                         rsurface.batchelement3s = NULL;
11305                         rsurface.batchelement3s_indexbuffer = NULL;
11306                         rsurface.batchelement3s_bufferoffset = 0;
11307                         if (endvertex <= 65536)
11308                         {
11309                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11310                                 for (i = 0;i < numtriangles*3;i++)
11311                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11312                         }
11313                         rsurface.batchfirsttriangle = firsttriangle;
11314                         rsurface.batchnumtriangles = numtriangles;
11315                 }
11316                 return;
11317         }
11318
11319         // something needs software processing, do it for real...
11320         // we only directly handle interleaved array data in this case...
11321         rsurface.batchgeneratedvertex = true;
11322
11323         // now copy the vertex data into a combined array and make an index array
11324         // (this is what Quake3 does all the time)
11325         //if (gaps || rsurface.batchfirstvertex)
11326         {
11327                 rsurface.batchvertexposition = NULL;
11328                 rsurface.batchvertexpositionbuffer = NULL;
11329                 rsurface.batchvertexmesh = NULL;
11330                 rsurface.batchvertexmeshbuffer = NULL;
11331                 rsurface.batchvertex3f = NULL;
11332                 rsurface.batchvertex3f_vertexbuffer = NULL;
11333                 rsurface.batchvertex3f_bufferoffset = 0;
11334                 rsurface.batchsvector3f = NULL;
11335                 rsurface.batchsvector3f_vertexbuffer = NULL;
11336                 rsurface.batchsvector3f_bufferoffset = 0;
11337                 rsurface.batchtvector3f = NULL;
11338                 rsurface.batchtvector3f_vertexbuffer = NULL;
11339                 rsurface.batchtvector3f_bufferoffset = 0;
11340                 rsurface.batchnormal3f = NULL;
11341                 rsurface.batchnormal3f_vertexbuffer = NULL;
11342                 rsurface.batchnormal3f_bufferoffset = 0;
11343                 rsurface.batchlightmapcolor4f = NULL;
11344                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11345                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11346                 rsurface.batchtexcoordtexture2f = NULL;
11347                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11348                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11349                 rsurface.batchtexcoordlightmap2f = NULL;
11350                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11351                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11352                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11353                 rsurface.batchelement3i_indexbuffer = NULL;
11354                 rsurface.batchelement3i_bufferoffset = 0;
11355                 rsurface.batchelement3s = NULL;
11356                 rsurface.batchelement3s_indexbuffer = NULL;
11357                 rsurface.batchelement3s_bufferoffset = 0;
11358                 // we'll only be setting up certain arrays as needed
11359                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11360                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11361                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11362                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11363                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11364                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11365                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11366                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11367                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11368                 {
11369                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11370                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11371                 }
11372                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11373                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11374                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11375                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11376                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11377                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11378                 numvertices = 0;
11379                 numtriangles = 0;
11380                 for (i = 0;i < texturenumsurfaces;i++)
11381                 {
11382                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11383                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11384                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11385                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11386                         // copy only the data requested
11387                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11388                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11389                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11390                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11391                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11392                         {
11393                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11394                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11395                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11396                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11397                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11398                                 {
11399                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11400                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11401                                 }
11402                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11403                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11404                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11405                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11406                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11407                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11408                         }
11409                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11410                         numvertices += surfacenumvertices;
11411                         numtriangles += surfacenumtriangles;
11412                 }
11413
11414                 // generate a 16bit index array as well if possible
11415                 // (in general, dynamic batches fit)
11416                 if (numvertices <= 65536)
11417                 {
11418                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11419                         for (i = 0;i < numtriangles*3;i++)
11420                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11421                 }
11422
11423                 // since we've copied everything, the batch now starts at 0
11424                 rsurface.batchfirstvertex = 0;
11425                 rsurface.batchnumvertices = numvertices;
11426                 rsurface.batchfirsttriangle = 0;
11427                 rsurface.batchnumtriangles = numtriangles;
11428         }
11429
11430         // q1bsp surfaces rendered in vertex color mode have to have colors
11431         // calculated based on lightstyles
11432         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11433         {
11434                 // generate color arrays for the surfaces in this list
11435                 int c[4];
11436                 int scale;
11437                 int size3;
11438                 const int *offsets;
11439                 const unsigned char *lm;
11440                 numvertices = 0;
11441                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11442                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11443                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11444                 for (i = 0;i < texturenumsurfaces;i++)
11445                 {
11446                         surface = texturesurfacelist[i];
11447                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11448                         surfacenumvertices = surface->num_vertices;
11449                         if (surface->lightmapinfo->samples)
11450                         {
11451                                 for (j = 0;j < surfacenumvertices;j++)
11452                                 {
11453                                         lm = surface->lightmapinfo->samples + offsets[j];
11454                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11455                                         VectorScale(lm, scale, c);
11456                                         if (surface->lightmapinfo->styles[1] != 255)
11457                                         {
11458                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11459                                                 lm += size3;
11460                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11461                                                 VectorMA(c, scale, lm, c);
11462                                                 if (surface->lightmapinfo->styles[2] != 255)
11463                                                 {
11464                                                         lm += size3;
11465                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11466                                                         VectorMA(c, scale, lm, c);
11467                                                         if (surface->lightmapinfo->styles[3] != 255)
11468                                                         {
11469                                                                 lm += size3;
11470                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11471                                                                 VectorMA(c, scale, lm, c);
11472                                                         }
11473                                                 }
11474                                         }
11475                                         c[0] >>= 15;
11476                                         c[1] >>= 15;
11477                                         c[2] >>= 15;
11478                                         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);
11479                                         numvertices++;
11480                                 }
11481                         }
11482                         else
11483                         {
11484                                 for (j = 0;j < surfacenumvertices;j++)
11485                                 {
11486                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11487                                         numvertices++;
11488                                 }
11489                         }
11490                 }
11491         }
11492
11493         // if vertices are deformed (sprite flares and things in maps, possibly
11494         // water waves, bulges and other deformations), modify the copied vertices
11495         // in place
11496         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11497         {
11498                 switch (deform->deform)
11499                 {
11500                 default:
11501                 case Q3DEFORM_PROJECTIONSHADOW:
11502                 case Q3DEFORM_TEXT0:
11503                 case Q3DEFORM_TEXT1:
11504                 case Q3DEFORM_TEXT2:
11505                 case Q3DEFORM_TEXT3:
11506                 case Q3DEFORM_TEXT4:
11507                 case Q3DEFORM_TEXT5:
11508                 case Q3DEFORM_TEXT6:
11509                 case Q3DEFORM_TEXT7:
11510                 case Q3DEFORM_NONE:
11511                         break;
11512                 case Q3DEFORM_AUTOSPRITE:
11513                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11514                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11515                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11516                         VectorNormalize(newforward);
11517                         VectorNormalize(newright);
11518                         VectorNormalize(newup);
11519                         // a single autosprite surface can contain multiple sprites...
11520                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11521                         {
11522                                 VectorClear(center);
11523                                 for (i = 0;i < 4;i++)
11524                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11525                                 VectorScale(center, 0.25f, center);
11526                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11527                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11528                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11529                                 for (i = 0;i < 4;i++)
11530                                 {
11531                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11532                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11533                                 }
11534                         }
11535                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11536                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11537                         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);
11538                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11539                         rsurface.batchvertex3f_vertexbuffer = NULL;
11540                         rsurface.batchvertex3f_bufferoffset = 0;
11541                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11542                         rsurface.batchsvector3f_vertexbuffer = NULL;
11543                         rsurface.batchsvector3f_bufferoffset = 0;
11544                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11545                         rsurface.batchtvector3f_vertexbuffer = NULL;
11546                         rsurface.batchtvector3f_bufferoffset = 0;
11547                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11548                         rsurface.batchnormal3f_vertexbuffer = NULL;
11549                         rsurface.batchnormal3f_bufferoffset = 0;
11550                         break;
11551                 case Q3DEFORM_AUTOSPRITE2:
11552                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11553                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11554                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11555                         VectorNormalize(newforward);
11556                         VectorNormalize(newright);
11557                         VectorNormalize(newup);
11558                         {
11559                                 const float *v1, *v2;
11560                                 vec3_t start, end;
11561                                 float f, l;
11562                                 struct
11563                                 {
11564                                         float length2;
11565                                         const float *v1;
11566                                         const float *v2;
11567                                 }
11568                                 shortest[2];
11569                                 memset(shortest, 0, sizeof(shortest));
11570                                 // a single autosprite surface can contain multiple sprites...
11571                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11572                                 {
11573                                         VectorClear(center);
11574                                         for (i = 0;i < 4;i++)
11575                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11576                                         VectorScale(center, 0.25f, center);
11577                                         // find the two shortest edges, then use them to define the
11578                                         // axis vectors for rotating around the central axis
11579                                         for (i = 0;i < 6;i++)
11580                                         {
11581                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11582                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11583                                                 l = VectorDistance2(v1, v2);
11584                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11585                                                 if (v1[2] != v2[2])
11586                                                         l += (1.0f / 1024.0f);
11587                                                 if (shortest[0].length2 > l || i == 0)
11588                                                 {
11589                                                         shortest[1] = shortest[0];
11590                                                         shortest[0].length2 = l;
11591                                                         shortest[0].v1 = v1;
11592                                                         shortest[0].v2 = v2;
11593                                                 }
11594                                                 else if (shortest[1].length2 > l || i == 1)
11595                                                 {
11596                                                         shortest[1].length2 = l;
11597                                                         shortest[1].v1 = v1;
11598                                                         shortest[1].v2 = v2;
11599                                                 }
11600                                         }
11601                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11602                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11603                                         // this calculates the right vector from the shortest edge
11604                                         // and the up vector from the edge midpoints
11605                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11606                                         VectorNormalize(right);
11607                                         VectorSubtract(end, start, up);
11608                                         VectorNormalize(up);
11609                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11610                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11611                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11612                                         VectorNegate(forward, forward);
11613                                         VectorReflect(forward, 0, up, forward);
11614                                         VectorNormalize(forward);
11615                                         CrossProduct(up, forward, newright);
11616                                         VectorNormalize(newright);
11617                                         // rotate the quad around the up axis vector, this is made
11618                                         // especially easy by the fact we know the quad is flat,
11619                                         // so we only have to subtract the center position and
11620                                         // measure distance along the right vector, and then
11621                                         // multiply that by the newright vector and add back the
11622                                         // center position
11623                                         // we also need to subtract the old position to undo the
11624                                         // displacement from the center, which we do with a
11625                                         // DotProduct, the subtraction/addition of center is also
11626                                         // optimized into DotProducts here
11627                                         l = DotProduct(right, center);
11628                                         for (i = 0;i < 4;i++)
11629                                         {
11630                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11631                                                 f = DotProduct(right, v1) - l;
11632                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11633                                         }
11634                                 }
11635                         }
11636                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11637                         rsurface.batchvertex3f_vertexbuffer = NULL;
11638                         rsurface.batchvertex3f_bufferoffset = 0;
11639                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11640                         {
11641                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11642                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11643                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11644                                 rsurface.batchnormal3f_bufferoffset = 0;
11645                         }
11646                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11647                         {
11648                                 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);
11649                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11650                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11651                                 rsurface.batchsvector3f_bufferoffset = 0;
11652                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11653                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11654                                 rsurface.batchtvector3f_bufferoffset = 0;
11655                         }
11656                         break;
11657                 case Q3DEFORM_NORMAL:
11658                         // deform the normals to make reflections wavey
11659                         for (j = 0;j < rsurface.batchnumvertices;j++)
11660                         {
11661                                 float vertex[3];
11662                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11663                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11664                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11665                                 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]);
11666                                 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]);
11667                                 VectorNormalize(normal);
11668                         }
11669                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11670                         rsurface.batchnormal3f_vertexbuffer = NULL;
11671                         rsurface.batchnormal3f_bufferoffset = 0;
11672                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11673                         {
11674                                 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);
11675                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11676                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11677                                 rsurface.batchsvector3f_bufferoffset = 0;
11678                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11679                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11680                                 rsurface.batchtvector3f_bufferoffset = 0;
11681                         }
11682                         break;
11683                 case Q3DEFORM_WAVE:
11684                         // deform vertex array to make wavey water and flags and such
11685                         waveparms[0] = deform->waveparms[0];
11686                         waveparms[1] = deform->waveparms[1];
11687                         waveparms[2] = deform->waveparms[2];
11688                         waveparms[3] = deform->waveparms[3];
11689                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11690                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11691                         // this is how a divisor of vertex influence on deformation
11692                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11693                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11694                         for (j = 0;j < rsurface.batchnumvertices;j++)
11695                         {
11696                                 // if the wavefunc depends on time, evaluate it per-vertex
11697                                 if (waveparms[3])
11698                                 {
11699                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11700                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11701                                 }
11702                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11703                         }
11704                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11705                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11706                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11707                         rsurface.batchvertex3f_vertexbuffer = NULL;
11708                         rsurface.batchvertex3f_bufferoffset = 0;
11709                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11710                         rsurface.batchnormal3f_vertexbuffer = NULL;
11711                         rsurface.batchnormal3f_bufferoffset = 0;
11712                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11713                         {
11714                                 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);
11715                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11716                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11717                                 rsurface.batchsvector3f_bufferoffset = 0;
11718                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11719                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11720                                 rsurface.batchtvector3f_bufferoffset = 0;
11721                         }
11722                         break;
11723                 case Q3DEFORM_BULGE:
11724                         // deform vertex array to make the surface have moving bulges
11725                         for (j = 0;j < rsurface.batchnumvertices;j++)
11726                         {
11727                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11728                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11729                         }
11730                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11731                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11732                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11733                         rsurface.batchvertex3f_vertexbuffer = NULL;
11734                         rsurface.batchvertex3f_bufferoffset = 0;
11735                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11736                         rsurface.batchnormal3f_vertexbuffer = NULL;
11737                         rsurface.batchnormal3f_bufferoffset = 0;
11738                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11739                         {
11740                                 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);
11741                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11742                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11743                                 rsurface.batchsvector3f_bufferoffset = 0;
11744                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11745                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11746                                 rsurface.batchtvector3f_bufferoffset = 0;
11747                         }
11748                         break;
11749                 case Q3DEFORM_MOVE:
11750                         // deform vertex array
11751                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11752                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11753                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11754                         VectorScale(deform->parms, scale, waveparms);
11755                         for (j = 0;j < rsurface.batchnumvertices;j++)
11756                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11757                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11758                         rsurface.batchvertex3f_vertexbuffer = NULL;
11759                         rsurface.batchvertex3f_bufferoffset = 0;
11760                         break;
11761                 }
11762         }
11763
11764         // generate texcoords based on the chosen texcoord source
11765         switch(rsurface.texture->tcgen.tcgen)
11766         {
11767         default:
11768         case Q3TCGEN_TEXTURE:
11769                 break;
11770         case Q3TCGEN_LIGHTMAP:
11771                 if (rsurface.batchtexcoordlightmap2f)
11772                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11773                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11774                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11775                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11776                 break;
11777         case Q3TCGEN_VECTOR:
11778                 for (j = 0;j < rsurface.batchnumvertices;j++)
11779                 {
11780                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11781                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11782                 }
11783                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11784                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11785                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11786                 break;
11787         case Q3TCGEN_ENVIRONMENT:
11788                 // make environment reflections using a spheremap
11789                 for (j = 0;j < rsurface.batchnumvertices;j++)
11790                 {
11791                         // identical to Q3A's method, but executed in worldspace so
11792                         // carried models can be shiny too
11793
11794                         float viewer[3], d, reflected[3], worldreflected[3];
11795
11796                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11797                         // VectorNormalize(viewer);
11798
11799                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11800
11801                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11802                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11803                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11804                         // note: this is proportinal to viewer, so we can normalize later
11805
11806                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11807                         VectorNormalize(worldreflected);
11808
11809                         // note: this sphere map only uses world x and z!
11810                         // so positive and negative y will LOOK THE SAME.
11811                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11812                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11813                 }
11814                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11815                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11816                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11817                 break;
11818         }
11819         // the only tcmod that needs software vertex processing is turbulent, so
11820         // check for it here and apply the changes if needed
11821         // and we only support that as the first one
11822         // (handling a mixture of turbulent and other tcmods would be problematic
11823         //  without punting it entirely to a software path)
11824         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11825         {
11826                 amplitude = rsurface.texture->tcmods[0].parms[1];
11827                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11828                 for (j = 0;j < rsurface.batchnumvertices;j++)
11829                 {
11830                         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);
11831                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11832                 }
11833                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11834                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11835                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11836         }
11837
11838         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11839         {
11840                 // convert the modified arrays to vertex structs
11841                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11842                 rsurface.batchvertexmeshbuffer = NULL;
11843                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11844                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11845                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11846                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11847                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11848                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11849                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11850                 {
11851                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11852                         {
11853                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11854                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11855                         }
11856                 }
11857                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11858                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11859                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11860                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11861                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11862                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11863                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11864                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11865                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11866         }
11867
11868         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11869         {
11870                 // convert the modified arrays to vertex structs
11871                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11872                 rsurface.batchvertexpositionbuffer = NULL;
11873                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11874                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11875                 else
11876                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11877                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11878         }
11879 }
11880
11881 void RSurf_DrawBatch(void)
11882 {
11883         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);
11884 }
11885
11886 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11887 {
11888         // pick the closest matching water plane
11889         int planeindex, vertexindex, bestplaneindex = -1;
11890         float d, bestd;
11891         vec3_t vert;
11892         const float *v;
11893         r_waterstate_waterplane_t *p;
11894         bestd = 0;
11895         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11896         {
11897                 if(p->camera_entity != rsurface.texture->camera_entity)
11898                         continue;
11899                 d = 0;
11900                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11901                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11902                 {
11903                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11904                         d += fabs(PlaneDiff(vert, &p->plane));
11905                 }
11906                 if (bestd > d || bestplaneindex < 0)
11907                 {
11908                         bestd = d;
11909                         bestplaneindex = planeindex;
11910                 }
11911         }
11912         return bestplaneindex;
11913 }
11914
11915 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11916 {
11917         int i;
11918         for (i = 0;i < rsurface.batchnumvertices;i++)
11919                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11920         rsurface.passcolor4f = rsurface.array_passcolor4f;
11921         rsurface.passcolor4f_vertexbuffer = 0;
11922         rsurface.passcolor4f_bufferoffset = 0;
11923 }
11924
11925 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11926 {
11927         int i;
11928         float f;
11929         const float *v;
11930         const float *c;
11931         float *c2;
11932         if (rsurface.passcolor4f)
11933         {
11934                 // generate color arrays
11935                 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)
11936                 {
11937                         f = RSurf_FogVertex(v);
11938                         c2[0] = c[0] * f;
11939                         c2[1] = c[1] * f;
11940                         c2[2] = c[2] * f;
11941                         c2[3] = c[3];
11942                 }
11943         }
11944         else
11945         {
11946                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11947                 {
11948                         f = RSurf_FogVertex(v);
11949                         c2[0] = f;
11950                         c2[1] = f;
11951                         c2[2] = f;
11952                         c2[3] = 1;
11953                 }
11954         }
11955         rsurface.passcolor4f = rsurface.array_passcolor4f;
11956         rsurface.passcolor4f_vertexbuffer = 0;
11957         rsurface.passcolor4f_bufferoffset = 0;
11958 }
11959
11960 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11961 {
11962         int i;
11963         float f;
11964         const float *v;
11965         const float *c;
11966         float *c2;
11967         if (!rsurface.passcolor4f)
11968                 return;
11969         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)
11970         {
11971                 f = RSurf_FogVertex(v);
11972                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11973                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11974                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11975                 c2[3] = c[3];
11976         }
11977         rsurface.passcolor4f = rsurface.array_passcolor4f;
11978         rsurface.passcolor4f_vertexbuffer = 0;
11979         rsurface.passcolor4f_bufferoffset = 0;
11980 }
11981
11982 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11983 {
11984         int i;
11985         const float *c;
11986         float *c2;
11987         if (!rsurface.passcolor4f)
11988                 return;
11989         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11990         {
11991                 c2[0] = c[0] * r;
11992                 c2[1] = c[1] * g;
11993                 c2[2] = c[2] * b;
11994                 c2[3] = c[3] * a;
11995         }
11996         rsurface.passcolor4f = rsurface.array_passcolor4f;
11997         rsurface.passcolor4f_vertexbuffer = 0;
11998         rsurface.passcolor4f_bufferoffset = 0;
11999 }
12000
12001 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12002 {
12003         int i;
12004         const float *c;
12005         float *c2;
12006         if (!rsurface.passcolor4f)
12007                 return;
12008         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12009         {
12010                 c2[0] = c[0] + r_refdef.scene.ambient;
12011                 c2[1] = c[1] + r_refdef.scene.ambient;
12012                 c2[2] = c[2] + r_refdef.scene.ambient;
12013                 c2[3] = c[3];
12014         }
12015         rsurface.passcolor4f = rsurface.array_passcolor4f;
12016         rsurface.passcolor4f_vertexbuffer = 0;
12017         rsurface.passcolor4f_bufferoffset = 0;
12018 }
12019
12020 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12021 {
12022         // TODO: optimize
12023         rsurface.passcolor4f = NULL;
12024         rsurface.passcolor4f_vertexbuffer = 0;
12025         rsurface.passcolor4f_bufferoffset = 0;
12026         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12027         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12028         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12029         GL_Color(r, g, b, a);
12030         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12031         RSurf_DrawBatch();
12032 }
12033
12034 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12035 {
12036         // TODO: optimize applyfog && applycolor case
12037         // just apply fog if necessary, and tint the fog color array if necessary
12038         rsurface.passcolor4f = NULL;
12039         rsurface.passcolor4f_vertexbuffer = 0;
12040         rsurface.passcolor4f_bufferoffset = 0;
12041         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12042         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12043         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12044         GL_Color(r, g, b, a);
12045         RSurf_DrawBatch();
12046 }
12047
12048 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12049 {
12050         // TODO: optimize
12051         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12052         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12053         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12054         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12055         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12056         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12057         GL_Color(r, g, b, a);
12058         RSurf_DrawBatch();
12059 }
12060
12061 static void RSurf_DrawBatch_GL11_ClampColor(void)
12062 {
12063         int i;
12064         const float *c1;
12065         float *c2;
12066         if (!rsurface.passcolor4f)
12067                 return;
12068         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12069         {
12070                 c2[0] = bound(0.0f, c1[0], 1.0f);
12071                 c2[1] = bound(0.0f, c1[1], 1.0f);
12072                 c2[2] = bound(0.0f, c1[2], 1.0f);
12073                 c2[3] = bound(0.0f, c1[3], 1.0f);
12074         }
12075 }
12076
12077 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12078 {
12079         int i;
12080         float f;
12081         float alpha;
12082         const float *v;
12083         const float *n;
12084         float *c;
12085         vec3_t ambientcolor;
12086         vec3_t diffusecolor;
12087         vec3_t lightdir;
12088         // TODO: optimize
12089         // model lighting
12090         VectorCopy(rsurface.modellight_lightdir, lightdir);
12091         f = 0.5f * r_refdef.lightmapintensity;
12092         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12093         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12094         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12095         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12096         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12097         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12098         alpha = *a;
12099         if (VectorLength2(diffusecolor) > 0)
12100         {
12101                 // q3-style directional shading
12102                 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)
12103                 {
12104                         if ((f = DotProduct(n, lightdir)) > 0)
12105                                 VectorMA(ambientcolor, f, diffusecolor, c);
12106                         else
12107                                 VectorCopy(ambientcolor, c);
12108                         c[3] = alpha;
12109                 }
12110                 *r = 1;
12111                 *g = 1;
12112                 *b = 1;
12113                 *a = 1;
12114                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12115                 rsurface.passcolor4f_vertexbuffer = 0;
12116                 rsurface.passcolor4f_bufferoffset = 0;
12117                 *applycolor = false;
12118         }
12119         else
12120         {
12121                 *r = ambientcolor[0];
12122                 *g = ambientcolor[1];
12123                 *b = ambientcolor[2];
12124                 rsurface.passcolor4f = NULL;
12125                 rsurface.passcolor4f_vertexbuffer = 0;
12126                 rsurface.passcolor4f_bufferoffset = 0;
12127         }
12128 }
12129
12130 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12131 {
12132         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12133         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12134         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12135         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12136         GL_Color(r, g, b, a);
12137         RSurf_DrawBatch();
12138 }
12139
12140 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12141 {
12142         int i;
12143         float f;
12144         const float *v;
12145         float *c;
12146         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12147         {
12148                 f = 1 - RSurf_FogVertex(v);
12149                 c[0] = r;
12150                 c[1] = g;
12151                 c[2] = b;
12152                 c[3] = f * a;
12153         }
12154 }
12155
12156 void RSurf_SetupDepthAndCulling(void)
12157 {
12158         // submodels are biased to avoid z-fighting with world surfaces that they
12159         // may be exactly overlapping (avoids z-fighting artifacts on certain
12160         // doors and things in Quake maps)
12161         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12162         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12163         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12164         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12165 }
12166
12167 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12168 {
12169         // transparent sky would be ridiculous
12170         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12171                 return;
12172         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12173         skyrenderlater = true;
12174         RSurf_SetupDepthAndCulling();
12175         GL_DepthMask(true);
12176         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12177         // skymasking on them, and Quake3 never did sky masking (unlike
12178         // software Quake and software Quake2), so disable the sky masking
12179         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12180         // and skymasking also looks very bad when noclipping outside the
12181         // level, so don't use it then either.
12182         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12183         {
12184                 R_Mesh_ResetTextureState();
12185                 if (skyrendermasked)
12186                 {
12187                         R_SetupShader_DepthOrShadow();
12188                         // depth-only (masking)
12189                         GL_ColorMask(0,0,0,0);
12190                         // just to make sure that braindead drivers don't draw
12191                         // anything despite that colormask...
12192                         GL_BlendFunc(GL_ZERO, GL_ONE);
12193                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12194                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12195                 }
12196                 else
12197                 {
12198                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12199                         // fog sky
12200                         GL_BlendFunc(GL_ONE, GL_ZERO);
12201                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12202                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12203                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12204                 }
12205                 RSurf_DrawBatch();
12206                 if (skyrendermasked)
12207                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12208         }
12209         R_Mesh_ResetTextureState();
12210         GL_Color(1, 1, 1, 1);
12211 }
12212
12213 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12214 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12215 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12216 {
12217         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12218                 return;
12219         if (prepass)
12220         {
12221                 // render screenspace normalmap to texture
12222                 GL_DepthMask(true);
12223                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12224                 RSurf_DrawBatch();
12225                 return;
12226         }
12227
12228         // bind lightmap texture
12229
12230         // water/refraction/reflection/camera surfaces have to be handled specially
12231         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12232         {
12233                 int start, end, startplaneindex;
12234                 for (start = 0;start < texturenumsurfaces;start = end)
12235                 {
12236                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12237                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12238                                 ;
12239                         // now that we have a batch using the same planeindex, render it
12240                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12241                         {
12242                                 // render water or distortion background
12243                                 GL_DepthMask(true);
12244                                 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));
12245                                 RSurf_DrawBatch();
12246                                 // blend surface on top
12247                                 GL_DepthMask(false);
12248                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12249                                 RSurf_DrawBatch();
12250                         }
12251                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12252                         {
12253                                 // render surface with reflection texture as input
12254                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12255                                 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));
12256                                 RSurf_DrawBatch();
12257                         }
12258                 }
12259                 return;
12260         }
12261
12262         // render surface batch normally
12263         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12264         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12265         RSurf_DrawBatch();
12266 }
12267
12268 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12269 {
12270         // OpenGL 1.3 path - anything not completely ancient
12271         qboolean applycolor;
12272         qboolean applyfog;
12273         int layerindex;
12274         const texturelayer_t *layer;
12275         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);
12276         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12277
12278         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12279         {
12280                 vec4_t layercolor;
12281                 int layertexrgbscale;
12282                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12283                 {
12284                         if (layerindex == 0)
12285                                 GL_AlphaTest(true);
12286                         else
12287                         {
12288                                 GL_AlphaTest(false);
12289                                 GL_DepthFunc(GL_EQUAL);
12290                         }
12291                 }
12292                 GL_DepthMask(layer->depthmask && writedepth);
12293                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12294                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12295                 {
12296                         layertexrgbscale = 4;
12297                         VectorScale(layer->color, 0.25f, layercolor);
12298                 }
12299                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12300                 {
12301                         layertexrgbscale = 2;
12302                         VectorScale(layer->color, 0.5f, layercolor);
12303                 }
12304                 else
12305                 {
12306                         layertexrgbscale = 1;
12307                         VectorScale(layer->color, 1.0f, layercolor);
12308                 }
12309                 layercolor[3] = layer->color[3];
12310                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12311                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12312                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12313                 switch (layer->type)
12314                 {
12315                 case TEXTURELAYERTYPE_LITTEXTURE:
12316                         // single-pass lightmapped texture with 2x rgbscale
12317                         R_Mesh_TexBind(0, r_texture_white);
12318                         R_Mesh_TexMatrix(0, NULL);
12319                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12320                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12321                         R_Mesh_TexBind(1, layer->texture);
12322                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12323                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12324                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12325                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12326                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12327                         else if (rsurface.uselightmaptexture)
12328                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12329                         else
12330                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12331                         break;
12332                 case TEXTURELAYERTYPE_TEXTURE:
12333                         // singletexture unlit texture with transparency support
12334                         R_Mesh_TexBind(0, layer->texture);
12335                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12336                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12337                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12338                         R_Mesh_TexBind(1, 0);
12339                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12340                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12341                         break;
12342                 case TEXTURELAYERTYPE_FOG:
12343                         // singletexture fogging
12344                         if (layer->texture)
12345                         {
12346                                 R_Mesh_TexBind(0, layer->texture);
12347                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12348                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12349                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12350                         }
12351                         else
12352                         {
12353                                 R_Mesh_TexBind(0, 0);
12354                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12355                         }
12356                         R_Mesh_TexBind(1, 0);
12357                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12358                         // generate a color array for the fog pass
12359                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12360                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12361                         RSurf_DrawBatch();
12362                         break;
12363                 default:
12364                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12365                 }
12366         }
12367         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12368         {
12369                 GL_DepthFunc(GL_LEQUAL);
12370                 GL_AlphaTest(false);
12371         }
12372 }
12373
12374 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12375 {
12376         // OpenGL 1.1 - crusty old voodoo path
12377         qboolean applyfog;
12378         int layerindex;
12379         const texturelayer_t *layer;
12380         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);
12381         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12382
12383         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12384         {
12385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12386                 {
12387                         if (layerindex == 0)
12388                                 GL_AlphaTest(true);
12389                         else
12390                         {
12391                                 GL_AlphaTest(false);
12392                                 GL_DepthFunc(GL_EQUAL);
12393                         }
12394                 }
12395                 GL_DepthMask(layer->depthmask && writedepth);
12396                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12397                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12398                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12399                 switch (layer->type)
12400                 {
12401                 case TEXTURELAYERTYPE_LITTEXTURE:
12402                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12403                         {
12404                                 // two-pass lit texture with 2x rgbscale
12405                                 // first the lightmap pass
12406                                 R_Mesh_TexBind(0, r_texture_white);
12407                                 R_Mesh_TexMatrix(0, NULL);
12408                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12409                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12410                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12411                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12412                                 else if (rsurface.uselightmaptexture)
12413                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12414                                 else
12415                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12416                                 // then apply the texture to it
12417                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12418                                 R_Mesh_TexBind(0, layer->texture);
12419                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12420                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12421                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12422                                 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);
12423                         }
12424                         else
12425                         {
12426                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12427                                 R_Mesh_TexBind(0, layer->texture);
12428                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12429                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12430                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12431                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12432                                         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);
12433                                 else
12434                                         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);
12435                         }
12436                         break;
12437                 case TEXTURELAYERTYPE_TEXTURE:
12438                         // singletexture unlit texture with transparency support
12439                         R_Mesh_TexBind(0, layer->texture);
12440                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12441                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12442                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12443                         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);
12444                         break;
12445                 case TEXTURELAYERTYPE_FOG:
12446                         // singletexture fogging
12447                         if (layer->texture)
12448                         {
12449                                 R_Mesh_TexBind(0, layer->texture);
12450                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12451                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12452                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12453                         }
12454                         else
12455                         {
12456                                 R_Mesh_TexBind(0, 0);
12457                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12458                         }
12459                         // generate a color array for the fog pass
12460                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12461                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12462                         RSurf_DrawBatch();
12463                         break;
12464                 default:
12465                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12466                 }
12467         }
12468         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12469         {
12470                 GL_DepthFunc(GL_LEQUAL);
12471                 GL_AlphaTest(false);
12472         }
12473 }
12474
12475 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12476 {
12477         int vi;
12478         int j;
12479         r_vertexgeneric_t *batchvertex;
12480         float c[4];
12481
12482         GL_AlphaTest(false);
12483         R_Mesh_ResetTextureState();
12484         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12485
12486         if(rsurface.texture && rsurface.texture->currentskinframe)
12487         {
12488                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12489                 c[3] *= rsurface.texture->currentalpha;
12490         }
12491         else
12492         {
12493                 c[0] = 1;
12494                 c[1] = 0;
12495                 c[2] = 1;
12496                 c[3] = 1;
12497         }
12498
12499         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12500         {
12501                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12502                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12503                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12504         }
12505
12506         // brighten it up (as texture value 127 means "unlit")
12507         c[0] *= 2 * r_refdef.view.colorscale;
12508         c[1] *= 2 * r_refdef.view.colorscale;
12509         c[2] *= 2 * r_refdef.view.colorscale;
12510
12511         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12512                 c[3] *= r_wateralpha.value;
12513
12514         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12515         {
12516                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12517                 GL_DepthMask(false);
12518         }
12519         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12520         {
12521                 GL_BlendFunc(GL_ONE, GL_ONE);
12522                 GL_DepthMask(false);
12523         }
12524         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12525         {
12526                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12527                 GL_DepthMask(false);
12528         }
12529         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12530         {
12531                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12532                 GL_DepthMask(false);
12533         }
12534         else
12535         {
12536                 GL_BlendFunc(GL_ONE, GL_ZERO);
12537                 GL_DepthMask(writedepth);
12538         }
12539
12540         if (r_showsurfaces.integer == 3)
12541         {
12542                 rsurface.passcolor4f = NULL;
12543
12544                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12545                 {
12546                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12547
12548                         rsurface.passcolor4f = NULL;
12549                         rsurface.passcolor4f_vertexbuffer = 0;
12550                         rsurface.passcolor4f_bufferoffset = 0;
12551                 }
12552                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12553                 {
12554                         qboolean applycolor = true;
12555                         float one = 1.0;
12556
12557                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12558
12559                         r_refdef.lightmapintensity = 1;
12560                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12561                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12562                 }
12563                 else
12564                 {
12565                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12566
12567                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12568                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12569                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12570                 }
12571
12572                 if(!rsurface.passcolor4f)
12573                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12574
12575                 RSurf_DrawBatch_GL11_ApplyAmbient();
12576                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12577                 if(r_refdef.fogenabled)
12578                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12579                 RSurf_DrawBatch_GL11_ClampColor();
12580
12581                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12582                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12583                 RSurf_DrawBatch();
12584         }
12585         else if (!r_refdef.view.showdebug)
12586         {
12587                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12588                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12589                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12590                 {
12591                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12592                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12593                 }
12594                 R_Mesh_PrepareVertices_Generic_Unlock();
12595                 RSurf_DrawBatch();
12596         }
12597         else if (r_showsurfaces.integer == 4)
12598         {
12599                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12600                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12601                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12602                 {
12603                         unsigned char c = vi << 3;
12604                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12605                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12606                 }
12607                 R_Mesh_PrepareVertices_Generic_Unlock();
12608                 RSurf_DrawBatch();
12609         }
12610         else if (r_showsurfaces.integer == 2)
12611         {
12612                 const int *e;
12613                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12614                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12615                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12616                 {
12617                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12618                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12619                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12620                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12621                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12622                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12623                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12624                 }
12625                 R_Mesh_PrepareVertices_Generic_Unlock();
12626                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12627         }
12628         else
12629         {
12630                 int texturesurfaceindex;
12631                 int k;
12632                 const msurface_t *surface;
12633                 unsigned char surfacecolor4ub[4];
12634                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12635                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12636                 vi = 0;
12637                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12638                 {
12639                         surface = texturesurfacelist[texturesurfaceindex];
12640                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12641                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12642                         for (j = 0;j < surface->num_vertices;j++)
12643                         {
12644                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12645                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12646                                 vi++;
12647                         }
12648                 }
12649                 R_Mesh_PrepareVertices_Generic_Unlock();
12650                 RSurf_DrawBatch();
12651         }
12652 }
12653
12654 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12655 {
12656         CHECKGLERROR
12657         RSurf_SetupDepthAndCulling();
12658         if (r_showsurfaces.integer)
12659         {
12660                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12661                 return;
12662         }
12663         switch (vid.renderpath)
12664         {
12665         case RENDERPATH_GL20:
12666         case RENDERPATH_CGGL:
12667         case RENDERPATH_D3D9:
12668         case RENDERPATH_D3D10:
12669         case RENDERPATH_D3D11:
12670                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12671                 break;
12672         case RENDERPATH_GL13:
12673                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12674                 break;
12675         case RENDERPATH_GL11:
12676                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12677                 break;
12678         }
12679         CHECKGLERROR
12680 }
12681
12682 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12683 {
12684         CHECKGLERROR
12685         RSurf_SetupDepthAndCulling();
12686         if (r_showsurfaces.integer)
12687         {
12688                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12689                 return;
12690         }
12691         switch (vid.renderpath)
12692         {
12693         case RENDERPATH_GL20:
12694         case RENDERPATH_CGGL:
12695         case RENDERPATH_D3D9:
12696         case RENDERPATH_D3D10:
12697         case RENDERPATH_D3D11:
12698                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12699                 break;
12700         case RENDERPATH_GL13:
12701                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12702                 break;
12703         case RENDERPATH_GL11:
12704                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12705                 break;
12706         }
12707         CHECKGLERROR
12708 }
12709
12710 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12711 {
12712         int i, j;
12713         int texturenumsurfaces, endsurface;
12714         texture_t *texture;
12715         const msurface_t *surface;
12716 #define MAXBATCH_TRANSPARENTSURFACES 256
12717         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12718
12719         // if the model is static it doesn't matter what value we give for
12720         // wantnormals and wanttangents, so this logic uses only rules applicable
12721         // to a model, knowing that they are meaningless otherwise
12722         if (ent == r_refdef.scene.worldentity)
12723                 RSurf_ActiveWorldEntity();
12724         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12725                 RSurf_ActiveModelEntity(ent, false, false, false);
12726         else
12727         {
12728                 switch (vid.renderpath)
12729                 {
12730                 case RENDERPATH_GL20:
12731                 case RENDERPATH_CGGL:
12732                 case RENDERPATH_D3D9:
12733                 case RENDERPATH_D3D10:
12734                 case RENDERPATH_D3D11:
12735                         RSurf_ActiveModelEntity(ent, true, true, false);
12736                         break;
12737                 case RENDERPATH_GL13:
12738                 case RENDERPATH_GL11:
12739                         RSurf_ActiveModelEntity(ent, true, false, false);
12740                         break;
12741                 }
12742         }
12743
12744         if (r_transparentdepthmasking.integer)
12745         {
12746                 qboolean setup = false;
12747                 for (i = 0;i < numsurfaces;i = j)
12748                 {
12749                         j = i + 1;
12750                         surface = rsurface.modelsurfaces + surfacelist[i];
12751                         texture = surface->texture;
12752                         rsurface.texture = R_GetCurrentTexture(texture);
12753                         rsurface.lightmaptexture = NULL;
12754                         rsurface.deluxemaptexture = NULL;
12755                         rsurface.uselightmaptexture = false;
12756                         // scan ahead until we find a different texture
12757                         endsurface = min(i + 1024, numsurfaces);
12758                         texturenumsurfaces = 0;
12759                         texturesurfacelist[texturenumsurfaces++] = surface;
12760                         for (;j < endsurface;j++)
12761                         {
12762                                 surface = rsurface.modelsurfaces + surfacelist[j];
12763                                 if (texture != surface->texture)
12764                                         break;
12765                                 texturesurfacelist[texturenumsurfaces++] = surface;
12766                         }
12767                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12768                                 continue;
12769                         // render the range of surfaces as depth
12770                         if (!setup)
12771                         {
12772                                 setup = true;
12773                                 GL_ColorMask(0,0,0,0);
12774                                 GL_Color(1,1,1,1);
12775                                 GL_DepthTest(true);
12776                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12777                                 GL_DepthMask(true);
12778                                 GL_AlphaTest(false);
12779                                 R_Mesh_ResetTextureState();
12780                                 R_SetupShader_DepthOrShadow();
12781                         }
12782                         RSurf_SetupDepthAndCulling();
12783                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12784                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12785                         RSurf_DrawBatch();
12786                 }
12787                 if (setup)
12788                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12789         }
12790
12791         for (i = 0;i < numsurfaces;i = j)
12792         {
12793                 j = i + 1;
12794                 surface = rsurface.modelsurfaces + surfacelist[i];
12795                 texture = surface->texture;
12796                 rsurface.texture = R_GetCurrentTexture(texture);
12797                 rsurface.lightmaptexture = surface->lightmaptexture;
12798                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12799                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12800                 // scan ahead until we find a different texture
12801                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12802                 texturenumsurfaces = 0;
12803                 texturesurfacelist[texturenumsurfaces++] = surface;
12804                 for (;j < endsurface;j++)
12805                 {
12806                         surface = rsurface.modelsurfaces + surfacelist[j];
12807                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12808                                 break;
12809                         texturesurfacelist[texturenumsurfaces++] = surface;
12810                 }
12811                 // render the range of surfaces
12812                 if (ent == r_refdef.scene.worldentity)
12813                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12814                 else
12815                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12816         }
12817         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12818         GL_AlphaTest(false);
12819 }
12820
12821 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12822 {
12823         // transparent surfaces get pushed off into the transparent queue
12824         int surfacelistindex;
12825         const msurface_t *surface;
12826         vec3_t tempcenter, center;
12827         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12828         {
12829                 surface = texturesurfacelist[surfacelistindex];
12830                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12831                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12832                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12833                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12834                 if (queueentity->transparent_offset) // transparent offset
12835                 {
12836                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12837                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12838                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12839                 }
12840                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12841         }
12842 }
12843
12844 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12845 {
12846         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12847                 return;
12848         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12849                 return;
12850         RSurf_SetupDepthAndCulling();
12851         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12852         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12853         RSurf_DrawBatch();
12854 }
12855
12856 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12857 {
12858         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12859         CHECKGLERROR
12860         if (depthonly)
12861                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12862         else if (prepass)
12863         {
12864                 if (!rsurface.texture->currentnumlayers)
12865                         return;
12866                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12867                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12868                 else
12869                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12870         }
12871         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12872                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12873         else if (!rsurface.texture->currentnumlayers)
12874                 return;
12875         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12876         {
12877                 // in the deferred case, transparent surfaces were queued during prepass
12878                 if (!r_shadow_usingdeferredprepass)
12879                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12880         }
12881         else
12882         {
12883                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12884                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12885         }
12886         CHECKGLERROR
12887 }
12888
12889 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12890 {
12891         int i, j;
12892         texture_t *texture;
12893         // break the surface list down into batches by texture and use of lightmapping
12894         for (i = 0;i < numsurfaces;i = j)
12895         {
12896                 j = i + 1;
12897                 // texture is the base texture pointer, rsurface.texture is the
12898                 // current frame/skin the texture is directing us to use (for example
12899                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12900                 // use skin 1 instead)
12901                 texture = surfacelist[i]->texture;
12902                 rsurface.texture = R_GetCurrentTexture(texture);
12903                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12904                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12905                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12906                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12907                 {
12908                         // if this texture is not the kind we want, skip ahead to the next one
12909                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12910                                 ;
12911                         continue;
12912                 }
12913                 // simply scan ahead until we find a different texture or lightmap state
12914                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12915                         ;
12916                 // render the range of surfaces
12917                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12918         }
12919 }
12920
12921 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12922 {
12923         CHECKGLERROR
12924         if (depthonly)
12925                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12926         else if (prepass)
12927         {
12928                 if (!rsurface.texture->currentnumlayers)
12929                         return;
12930                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12931                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12932                 else
12933                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12934         }
12935         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12936                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12937         else if (!rsurface.texture->currentnumlayers)
12938                 return;
12939         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12940         {
12941                 // in the deferred case, transparent surfaces were queued during prepass
12942                 if (!r_shadow_usingdeferredprepass)
12943                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12944         }
12945         else
12946         {
12947                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12948                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12949         }
12950         CHECKGLERROR
12951 }
12952
12953 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12954 {
12955         int i, j;
12956         texture_t *texture;
12957         // break the surface list down into batches by texture and use of lightmapping
12958         for (i = 0;i < numsurfaces;i = j)
12959         {
12960                 j = i + 1;
12961                 // texture is the base texture pointer, rsurface.texture is the
12962                 // current frame/skin the texture is directing us to use (for example
12963                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12964                 // use skin 1 instead)
12965                 texture = surfacelist[i]->texture;
12966                 rsurface.texture = R_GetCurrentTexture(texture);
12967                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12968                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12969                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12970                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12971                 {
12972                         // if this texture is not the kind we want, skip ahead to the next one
12973                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12974                                 ;
12975                         continue;
12976                 }
12977                 // simply scan ahead until we find a different texture or lightmap state
12978                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12979                         ;
12980                 // render the range of surfaces
12981                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12982         }
12983 }
12984
12985 float locboxvertex3f[6*4*3] =
12986 {
12987         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12988         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12989         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12990         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12991         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12992         1,0,0, 0,0,0, 0,1,0, 1,1,0
12993 };
12994
12995 unsigned short locboxelements[6*2*3] =
12996 {
12997          0, 1, 2, 0, 2, 3,
12998          4, 5, 6, 4, 6, 7,
12999          8, 9,10, 8,10,11,
13000         12,13,14, 12,14,15,
13001         16,17,18, 16,18,19,
13002         20,21,22, 20,22,23
13003 };
13004
13005 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13006 {
13007         int i, j;
13008         cl_locnode_t *loc = (cl_locnode_t *)ent;
13009         vec3_t mins, size;
13010         float vertex3f[6*4*3];
13011         CHECKGLERROR
13012         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13013         GL_DepthMask(false);
13014         GL_DepthRange(0, 1);
13015         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13016         GL_DepthTest(true);
13017         GL_CullFace(GL_NONE);
13018         R_EntityMatrix(&identitymatrix);
13019
13020         R_Mesh_ResetTextureState();
13021
13022         i = surfacelist[0];
13023         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13024                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13025                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13026                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13027
13028         if (VectorCompare(loc->mins, loc->maxs))
13029         {
13030                 VectorSet(size, 2, 2, 2);
13031                 VectorMA(loc->mins, -0.5f, size, mins);
13032         }
13033         else
13034         {
13035                 VectorCopy(loc->mins, mins);
13036                 VectorSubtract(loc->maxs, loc->mins, size);
13037         }
13038
13039         for (i = 0;i < 6*4*3;)
13040                 for (j = 0;j < 3;j++, i++)
13041                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13042
13043         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13044         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13045         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13046 }
13047
13048 void R_DrawLocs(void)
13049 {
13050         int index;
13051         cl_locnode_t *loc, *nearestloc;
13052         vec3_t center;
13053         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13054         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13055         {
13056                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13057                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13058         }
13059 }
13060
13061 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13062 {
13063         if (decalsystem->decals)
13064                 Mem_Free(decalsystem->decals);
13065         memset(decalsystem, 0, sizeof(*decalsystem));
13066 }
13067
13068 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)
13069 {
13070         tridecal_t *decal;
13071         tridecal_t *decals;
13072         int i;
13073
13074         // expand or initialize the system
13075         if (decalsystem->maxdecals <= decalsystem->numdecals)
13076         {
13077                 decalsystem_t old = *decalsystem;
13078                 qboolean useshortelements;
13079                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13080                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13081                 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)));
13082                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13083                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13084                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13085                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13086                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13087                 if (decalsystem->numdecals)
13088                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13089                 if (old.decals)
13090                         Mem_Free(old.decals);
13091                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13092                         decalsystem->element3i[i] = i;
13093                 if (useshortelements)
13094                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13095                                 decalsystem->element3s[i] = i;
13096         }
13097
13098         // grab a decal and search for another free slot for the next one
13099         decals = decalsystem->decals;
13100         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13101         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13102                 ;
13103         decalsystem->freedecal = i;
13104         if (decalsystem->numdecals <= i)
13105                 decalsystem->numdecals = i + 1;
13106
13107         // initialize the decal
13108         decal->lived = 0;
13109         decal->triangleindex = triangleindex;
13110         decal->surfaceindex = surfaceindex;
13111         decal->decalsequence = decalsequence;
13112         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13113         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13114         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13115         decal->color4ub[0][3] = 255;
13116         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13117         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13118         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13119         decal->color4ub[1][3] = 255;
13120         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13121         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13122         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13123         decal->color4ub[2][3] = 255;
13124         decal->vertex3f[0][0] = v0[0];
13125         decal->vertex3f[0][1] = v0[1];
13126         decal->vertex3f[0][2] = v0[2];
13127         decal->vertex3f[1][0] = v1[0];
13128         decal->vertex3f[1][1] = v1[1];
13129         decal->vertex3f[1][2] = v1[2];
13130         decal->vertex3f[2][0] = v2[0];
13131         decal->vertex3f[2][1] = v2[1];
13132         decal->vertex3f[2][2] = v2[2];
13133         decal->texcoord2f[0][0] = t0[0];
13134         decal->texcoord2f[0][1] = t0[1];
13135         decal->texcoord2f[1][0] = t1[0];
13136         decal->texcoord2f[1][1] = t1[1];
13137         decal->texcoord2f[2][0] = t2[0];
13138         decal->texcoord2f[2][1] = t2[1];
13139 }
13140
13141 extern cvar_t cl_decals_bias;
13142 extern cvar_t cl_decals_models;
13143 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13144 // baseparms, parms, temps
13145 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)
13146 {
13147         int cornerindex;
13148         int index;
13149         float v[9][3];
13150         const float *vertex3f;
13151         int numpoints;
13152         float points[2][9][3];
13153         float temp[3];
13154         float tc[9][2];
13155         float f;
13156         float c[9][4];
13157         const int *e;
13158
13159         e = rsurface.modelelement3i + 3*triangleindex;
13160
13161         vertex3f = rsurface.modelvertex3f;
13162
13163         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13164         {
13165                 index = 3*e[cornerindex];
13166                 VectorCopy(vertex3f + index, v[cornerindex]);
13167         }
13168         // cull backfaces
13169         //TriangleNormal(v[0], v[1], v[2], normal);
13170         //if (DotProduct(normal, localnormal) < 0.0f)
13171         //      continue;
13172         // clip by each of the box planes formed from the projection matrix
13173         // if anything survives, we emit the decal
13174         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]);
13175         if (numpoints < 3)
13176                 return;
13177         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]);
13178         if (numpoints < 3)
13179                 return;
13180         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]);
13181         if (numpoints < 3)
13182                 return;
13183         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]);
13184         if (numpoints < 3)
13185                 return;
13186         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]);
13187         if (numpoints < 3)
13188                 return;
13189         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]);
13190         if (numpoints < 3)
13191                 return;
13192         // some part of the triangle survived, so we have to accept it...
13193         if (dynamic)
13194         {
13195                 // dynamic always uses the original triangle
13196                 numpoints = 3;
13197                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13198                 {
13199                         index = 3*e[cornerindex];
13200                         VectorCopy(vertex3f + index, v[cornerindex]);
13201                 }
13202         }
13203         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13204         {
13205                 // convert vertex positions to texcoords
13206                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13207                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13208                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13209                 // calculate distance fade from the projection origin
13210                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13211                 f = bound(0.0f, f, 1.0f);
13212                 c[cornerindex][0] = r * f;
13213                 c[cornerindex][1] = g * f;
13214                 c[cornerindex][2] = b * f;
13215                 c[cornerindex][3] = 1.0f;
13216                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13217         }
13218         if (dynamic)
13219                 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);
13220         else
13221                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13222                         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);
13223 }
13224 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)
13225 {
13226         matrix4x4_t projection;
13227         decalsystem_t *decalsystem;
13228         qboolean dynamic;
13229         dp_model_t *model;
13230         const msurface_t *surface;
13231         const msurface_t *surfaces;
13232         const int *surfacelist;
13233         const texture_t *texture;
13234         int numtriangles;
13235         int numsurfacelist;
13236         int surfacelistindex;
13237         int surfaceindex;
13238         int triangleindex;
13239         float localorigin[3];
13240         float localnormal[3];
13241         float localmins[3];
13242         float localmaxs[3];
13243         float localsize;
13244         //float normal[3];
13245         float planes[6][4];
13246         float angles[3];
13247         bih_t *bih;
13248         int bih_triangles_count;
13249         int bih_triangles[256];
13250         int bih_surfaces[256];
13251
13252         decalsystem = &ent->decalsystem;
13253         model = ent->model;
13254         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13255         {
13256                 R_DecalSystem_Reset(&ent->decalsystem);
13257                 return;
13258         }
13259
13260         if (!model->brush.data_leafs && !cl_decals_models.integer)
13261         {
13262                 if (decalsystem->model)
13263                         R_DecalSystem_Reset(decalsystem);
13264                 return;
13265         }
13266
13267         if (decalsystem->model != model)
13268                 R_DecalSystem_Reset(decalsystem);
13269         decalsystem->model = model;
13270
13271         RSurf_ActiveModelEntity(ent, false, false, false);
13272
13273         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13274         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13275         VectorNormalize(localnormal);
13276         localsize = worldsize*rsurface.inversematrixscale;
13277         localmins[0] = localorigin[0] - localsize;
13278         localmins[1] = localorigin[1] - localsize;
13279         localmins[2] = localorigin[2] - localsize;
13280         localmaxs[0] = localorigin[0] + localsize;
13281         localmaxs[1] = localorigin[1] + localsize;
13282         localmaxs[2] = localorigin[2] + localsize;
13283
13284         //VectorCopy(localnormal, planes[4]);
13285         //VectorVectors(planes[4], planes[2], planes[0]);
13286         AnglesFromVectors(angles, localnormal, NULL, false);
13287         AngleVectors(angles, planes[0], planes[2], planes[4]);
13288         VectorNegate(planes[0], planes[1]);
13289         VectorNegate(planes[2], planes[3]);
13290         VectorNegate(planes[4], planes[5]);
13291         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13292         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13293         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13294         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13295         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13296         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13297
13298 #if 1
13299 // works
13300 {
13301         matrix4x4_t forwardprojection;
13302         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13303         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13304 }
13305 #else
13306 // broken
13307 {
13308         float projectionvector[4][3];
13309         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13310         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13311         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13312         projectionvector[0][0] = planes[0][0] * ilocalsize;
13313         projectionvector[0][1] = planes[1][0] * ilocalsize;
13314         projectionvector[0][2] = planes[2][0] * ilocalsize;
13315         projectionvector[1][0] = planes[0][1] * ilocalsize;
13316         projectionvector[1][1] = planes[1][1] * ilocalsize;
13317         projectionvector[1][2] = planes[2][1] * ilocalsize;
13318         projectionvector[2][0] = planes[0][2] * ilocalsize;
13319         projectionvector[2][1] = planes[1][2] * ilocalsize;
13320         projectionvector[2][2] = planes[2][2] * ilocalsize;
13321         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13322         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13323         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13324         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13325 }
13326 #endif
13327
13328         dynamic = model->surfmesh.isanimated;
13329         numsurfacelist = model->nummodelsurfaces;
13330         surfacelist = model->sortedmodelsurfaces;
13331         surfaces = model->data_surfaces;
13332
13333         bih = NULL;
13334         bih_triangles_count = -1;
13335         if(!dynamic)
13336         {
13337                 if(model->render_bih.numleafs)
13338                         bih = &model->render_bih;
13339                 else if(model->collision_bih.numleafs)
13340                         bih = &model->collision_bih;
13341         }
13342         if(bih)
13343                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13344         if(bih_triangles_count == 0)
13345                 return;
13346         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13347                 return;
13348         if(bih_triangles_count > 0)
13349         {
13350                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13351                 {
13352                         surfaceindex = bih_surfaces[triangleindex];
13353                         surface = surfaces + surfaceindex;
13354                         texture = surface->texture;
13355                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13356                                 continue;
13357                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13358                                 continue;
13359                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13360                 }
13361         }
13362         else
13363         {
13364                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13365                 {
13366                         surfaceindex = surfacelist[surfacelistindex];
13367                         surface = surfaces + surfaceindex;
13368                         // check cull box first because it rejects more than any other check
13369                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13370                                 continue;
13371                         // skip transparent surfaces
13372                         texture = surface->texture;
13373                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13374                                 continue;
13375                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13376                                 continue;
13377                         numtriangles = surface->num_triangles;
13378                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13379                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13380                 }
13381         }
13382 }
13383
13384 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13385 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)
13386 {
13387         int renderentityindex;
13388         float worldmins[3];
13389         float worldmaxs[3];
13390         entity_render_t *ent;
13391
13392         if (!cl_decals_newsystem.integer)
13393                 return;
13394
13395         worldmins[0] = worldorigin[0] - worldsize;
13396         worldmins[1] = worldorigin[1] - worldsize;
13397         worldmins[2] = worldorigin[2] - worldsize;
13398         worldmaxs[0] = worldorigin[0] + worldsize;
13399         worldmaxs[1] = worldorigin[1] + worldsize;
13400         worldmaxs[2] = worldorigin[2] + worldsize;
13401
13402         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13403
13404         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13405         {
13406                 ent = r_refdef.scene.entities[renderentityindex];
13407                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13408                         continue;
13409
13410                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13411         }
13412 }
13413
13414 typedef struct r_decalsystem_splatqueue_s
13415 {
13416         vec3_t worldorigin;
13417         vec3_t worldnormal;
13418         float color[4];
13419         float tcrange[4];
13420         float worldsize;
13421         int decalsequence;
13422 }
13423 r_decalsystem_splatqueue_t;
13424
13425 int r_decalsystem_numqueued = 0;
13426 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13427
13428 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)
13429 {
13430         r_decalsystem_splatqueue_t *queue;
13431
13432         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13433                 return;
13434
13435         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13436         VectorCopy(worldorigin, queue->worldorigin);
13437         VectorCopy(worldnormal, queue->worldnormal);
13438         Vector4Set(queue->color, r, g, b, a);
13439         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13440         queue->worldsize = worldsize;
13441         queue->decalsequence = cl.decalsequence++;
13442 }
13443
13444 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13445 {
13446         int i;
13447         r_decalsystem_splatqueue_t *queue;
13448
13449         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13450                 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);
13451         r_decalsystem_numqueued = 0;
13452 }
13453
13454 extern cvar_t cl_decals_max;
13455 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13456 {
13457         int i;
13458         decalsystem_t *decalsystem = &ent->decalsystem;
13459         int numdecals;
13460         int killsequence;
13461         tridecal_t *decal;
13462         float frametime;
13463         float lifetime;
13464
13465         if (!decalsystem->numdecals)
13466                 return;
13467
13468         if (r_showsurfaces.integer)
13469                 return;
13470
13471         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13472         {
13473                 R_DecalSystem_Reset(decalsystem);
13474                 return;
13475         }
13476
13477         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13478         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13479
13480         if (decalsystem->lastupdatetime)
13481                 frametime = (cl.time - decalsystem->lastupdatetime);
13482         else
13483                 frametime = 0;
13484         decalsystem->lastupdatetime = cl.time;
13485         decal = decalsystem->decals;
13486         numdecals = decalsystem->numdecals;
13487
13488         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13489         {
13490                 if (decal->color4ub[0][3])
13491                 {
13492                         decal->lived += frametime;
13493                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13494                         {
13495                                 memset(decal, 0, sizeof(*decal));
13496                                 if (decalsystem->freedecal > i)
13497                                         decalsystem->freedecal = i;
13498                         }
13499                 }
13500         }
13501         decal = decalsystem->decals;
13502         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13503                 numdecals--;
13504
13505         // collapse the array by shuffling the tail decals into the gaps
13506         for (;;)
13507         {
13508                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13509                         decalsystem->freedecal++;
13510                 if (decalsystem->freedecal == numdecals)
13511                         break;
13512                 decal[decalsystem->freedecal] = decal[--numdecals];
13513         }
13514
13515         decalsystem->numdecals = numdecals;
13516
13517         if (numdecals <= 0)
13518         {
13519                 // if there are no decals left, reset decalsystem
13520                 R_DecalSystem_Reset(decalsystem);
13521         }
13522 }
13523
13524 extern skinframe_t *decalskinframe;
13525 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13526 {
13527         int i;
13528         decalsystem_t *decalsystem = &ent->decalsystem;
13529         int numdecals;
13530         tridecal_t *decal;
13531         float faderate;
13532         float alpha;
13533         float *v3f;
13534         float *c4f;
13535         float *t2f;
13536         const int *e;
13537         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13538         int numtris = 0;
13539
13540         numdecals = decalsystem->numdecals;
13541         if (!numdecals)
13542                 return;
13543
13544         if (r_showsurfaces.integer)
13545                 return;
13546
13547         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13548         {
13549                 R_DecalSystem_Reset(decalsystem);
13550                 return;
13551         }
13552
13553         // if the model is static it doesn't matter what value we give for
13554         // wantnormals and wanttangents, so this logic uses only rules applicable
13555         // to a model, knowing that they are meaningless otherwise
13556         if (ent == r_refdef.scene.worldentity)
13557                 RSurf_ActiveWorldEntity();
13558         else
13559                 RSurf_ActiveModelEntity(ent, false, false, false);
13560
13561         decalsystem->lastupdatetime = cl.time;
13562         decal = decalsystem->decals;
13563
13564         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13565
13566         // update vertex positions for animated models
13567         v3f = decalsystem->vertex3f;
13568         c4f = decalsystem->color4f;
13569         t2f = decalsystem->texcoord2f;
13570         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13571         {
13572                 if (!decal->color4ub[0][3])
13573                         continue;
13574
13575                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13576                         continue;
13577
13578                 // update color values for fading decals
13579                 if (decal->lived >= cl_decals_time.value)
13580                 {
13581                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13582                         alpha *= (1.0f/255.0f);
13583                 }
13584                 else
13585                         alpha = 1.0f/255.0f;
13586
13587                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13588                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13589                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13590                 c4f[ 3] = 1;
13591                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13592                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13593                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13594                 c4f[ 7] = 1;
13595                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13596                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13597                 c4f[10] = decal->color4ub[2][2] * alpha;
13598                 c4f[11] = 1;
13599
13600                 t2f[0] = decal->texcoord2f[0][0];
13601                 t2f[1] = decal->texcoord2f[0][1];
13602                 t2f[2] = decal->texcoord2f[1][0];
13603                 t2f[3] = decal->texcoord2f[1][1];
13604                 t2f[4] = decal->texcoord2f[2][0];
13605                 t2f[5] = decal->texcoord2f[2][1];
13606
13607                 // update vertex positions for animated models
13608                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13609                 {
13610                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13611                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13612                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13613                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13614                 }
13615                 else
13616                 {
13617                         VectorCopy(decal->vertex3f[0], v3f);
13618                         VectorCopy(decal->vertex3f[1], v3f + 3);
13619                         VectorCopy(decal->vertex3f[2], v3f + 6);
13620                 }
13621
13622                 if (r_refdef.fogenabled)
13623                 {
13624                         alpha = RSurf_FogVertex(v3f);
13625                         VectorScale(c4f, alpha, c4f);
13626                         alpha = RSurf_FogVertex(v3f + 3);
13627                         VectorScale(c4f + 4, alpha, c4f + 4);
13628                         alpha = RSurf_FogVertex(v3f + 6);
13629                         VectorScale(c4f + 8, alpha, c4f + 8);
13630                 }
13631
13632                 v3f += 9;
13633                 c4f += 12;
13634                 t2f += 6;
13635                 numtris++;
13636         }
13637
13638         if (numtris > 0)
13639         {
13640                 r_refdef.stats.drawndecals += numtris;
13641
13642                 // now render the decals all at once
13643                 // (this assumes they all use one particle font texture!)
13644                 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);
13645                 R_Mesh_ResetTextureState();
13646                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13647                 GL_DepthMask(false);
13648                 GL_DepthRange(0, 1);
13649                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13650                 GL_DepthTest(true);
13651                 GL_CullFace(GL_NONE);
13652                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13653                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13654                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13655         }
13656 }
13657
13658 static void R_DrawModelDecals(void)
13659 {
13660         int i, numdecals;
13661
13662         // fade faster when there are too many decals
13663         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13664         for (i = 0;i < r_refdef.scene.numentities;i++)
13665                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13666
13667         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13668         for (i = 0;i < r_refdef.scene.numentities;i++)
13669                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13670                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13671
13672         R_DecalSystem_ApplySplatEntitiesQueue();
13673
13674         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13675         for (i = 0;i < r_refdef.scene.numentities;i++)
13676                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13677
13678         r_refdef.stats.totaldecals += numdecals;
13679
13680         if (r_showsurfaces.integer)
13681                 return;
13682
13683         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13684
13685         for (i = 0;i < r_refdef.scene.numentities;i++)
13686         {
13687                 if (!r_refdef.viewcache.entityvisible[i])
13688                         continue;
13689                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13690                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13691         }
13692 }
13693
13694 extern cvar_t mod_collision_bih;
13695 void R_DrawDebugModel(void)
13696 {
13697         entity_render_t *ent = rsurface.entity;
13698         int i, j, k, l, flagsmask;
13699         const msurface_t *surface;
13700         dp_model_t *model = ent->model;
13701         vec3_t v;
13702
13703         switch(vid.renderpath)
13704         {
13705         case RENDERPATH_GL11:
13706         case RENDERPATH_GL13:
13707         case RENDERPATH_GL20:
13708         case RENDERPATH_CGGL:
13709                 break;
13710         case RENDERPATH_D3D9:
13711                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13712                 return;
13713         case RENDERPATH_D3D10:
13714                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13715                 return;
13716         case RENDERPATH_D3D11:
13717                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13718                 return;
13719         }
13720
13721         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13722
13723         R_Mesh_ResetTextureState();
13724         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13725         GL_DepthRange(0, 1);
13726         GL_DepthTest(!r_showdisabledepthtest.integer);
13727         GL_DepthMask(false);
13728         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13729
13730         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13731         {
13732                 int triangleindex;
13733                 int bihleafindex;
13734                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13735                 const q3mbrush_t *brush;
13736                 const bih_t *bih = &model->collision_bih;
13737                 const bih_leaf_t *bihleaf;
13738                 float vertex3f[3][3];
13739                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13740                 cullbox = false;
13741                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13742                 {
13743                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13744                                 continue;
13745                         switch (bihleaf->type)
13746                         {
13747                         case BIH_BRUSH:
13748                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13749                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13750                                 {
13751                                         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);
13752                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13753                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13754                                 }
13755                                 break;
13756                         case BIH_COLLISIONTRIANGLE:
13757                                 triangleindex = bihleaf->itemindex;
13758                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13759                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13760                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13761                                 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);
13762                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13763                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13764                                 break;
13765                         case BIH_RENDERTRIANGLE:
13766                                 triangleindex = bihleaf->itemindex;
13767                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13768                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13769                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13770                                 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);
13771                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13772                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13773                                 break;
13774                         }
13775                 }
13776         }
13777
13778         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13779
13780         if (r_showtris.integer || r_shownormals.integer)
13781         {
13782                 if (r_showdisabledepthtest.integer)
13783                 {
13784                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13785                         GL_DepthMask(false);
13786                 }
13787                 else
13788                 {
13789                         GL_BlendFunc(GL_ONE, GL_ZERO);
13790                         GL_DepthMask(true);
13791                 }
13792                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13793                 {
13794                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13795                                 continue;
13796                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13797                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13798                         {
13799                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13800                                 if (r_showtris.value > 0)
13801                                 {
13802                                         if (!rsurface.texture->currentlayers->depthmask)
13803                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13804                                         else if (ent == r_refdef.scene.worldentity)
13805                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13806                                         else
13807                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13808                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13809                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13810                                         RSurf_DrawBatch();
13811                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13812                                         CHECKGLERROR
13813                                 }
13814                                 if (r_shownormals.value < 0)
13815                                 {
13816                                         qglBegin(GL_LINES);
13817                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13818                                         {
13819                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13820                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13821                                                 qglVertex3f(v[0], v[1], v[2]);
13822                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13823                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13824                                                 qglVertex3f(v[0], v[1], v[2]);
13825                                         }
13826                                         qglEnd();
13827                                         CHECKGLERROR
13828                                 }
13829                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13830                                 {
13831                                         qglBegin(GL_LINES);
13832                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13833                                         {
13834                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13835                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13836                                                 qglVertex3f(v[0], v[1], v[2]);
13837                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13838                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13839                                                 qglVertex3f(v[0], v[1], v[2]);
13840                                         }
13841                                         qglEnd();
13842                                         CHECKGLERROR
13843                                         qglBegin(GL_LINES);
13844                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13845                                         {
13846                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13847                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13848                                                 qglVertex3f(v[0], v[1], v[2]);
13849                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13850                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13851                                                 qglVertex3f(v[0], v[1], v[2]);
13852                                         }
13853                                         qglEnd();
13854                                         CHECKGLERROR
13855                                         qglBegin(GL_LINES);
13856                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13857                                         {
13858                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13859                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13860                                                 qglVertex3f(v[0], v[1], v[2]);
13861                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13862                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13863                                                 qglVertex3f(v[0], v[1], v[2]);
13864                                         }
13865                                         qglEnd();
13866                                         CHECKGLERROR
13867                                 }
13868                         }
13869                 }
13870                 rsurface.texture = NULL;
13871         }
13872 }
13873
13874 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13875 int r_maxsurfacelist = 0;
13876 const msurface_t **r_surfacelist = NULL;
13877 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13878 {
13879         int i, j, endj, flagsmask;
13880         dp_model_t *model = r_refdef.scene.worldmodel;
13881         msurface_t *surfaces;
13882         unsigned char *update;
13883         int numsurfacelist = 0;
13884         if (model == NULL)
13885                 return;
13886
13887         if (r_maxsurfacelist < model->num_surfaces)
13888         {
13889                 r_maxsurfacelist = model->num_surfaces;
13890                 if (r_surfacelist)
13891                         Mem_Free((msurface_t**)r_surfacelist);
13892                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13893         }
13894
13895         RSurf_ActiveWorldEntity();
13896
13897         surfaces = model->data_surfaces;
13898         update = model->brushq1.lightmapupdateflags;
13899
13900         // update light styles on this submodel
13901         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13902         {
13903                 model_brush_lightstyleinfo_t *style;
13904                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13905                 {
13906                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13907                         {
13908                                 int *list = style->surfacelist;
13909                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13910                                 for (j = 0;j < style->numsurfaces;j++)
13911                                         update[list[j]] = true;
13912                         }
13913                 }
13914         }
13915
13916         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13917
13918         if (debug)
13919         {
13920                 R_DrawDebugModel();
13921                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13922                 return;
13923         }
13924
13925         rsurface.lightmaptexture = NULL;
13926         rsurface.deluxemaptexture = NULL;
13927         rsurface.uselightmaptexture = false;
13928         rsurface.texture = NULL;
13929         rsurface.rtlight = NULL;
13930         numsurfacelist = 0;
13931         // add visible surfaces to draw list
13932         for (i = 0;i < model->nummodelsurfaces;i++)
13933         {
13934                 j = model->sortedmodelsurfaces[i];
13935                 if (r_refdef.viewcache.world_surfacevisible[j])
13936                         r_surfacelist[numsurfacelist++] = surfaces + j;
13937         }
13938         // update lightmaps if needed
13939         if (model->brushq1.firstrender)
13940         {
13941                 model->brushq1.firstrender = false;
13942                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13943                         if (update[j])
13944                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13945         }
13946         else if (update)
13947         {
13948                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13949                         if (r_refdef.viewcache.world_surfacevisible[j])
13950                                 if (update[j])
13951                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13952         }
13953         // don't do anything if there were no surfaces
13954         if (!numsurfacelist)
13955         {
13956                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13957                 return;
13958         }
13959         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13960         GL_AlphaTest(false);
13961
13962         // add to stats if desired
13963         if (r_speeds.integer && !skysurfaces && !depthonly)
13964         {
13965                 r_refdef.stats.world_surfaces += numsurfacelist;
13966                 for (j = 0;j < numsurfacelist;j++)
13967                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13968         }
13969
13970         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13971 }
13972
13973 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13974 {
13975         int i, j, endj, flagsmask;
13976         dp_model_t *model = ent->model;
13977         msurface_t *surfaces;
13978         unsigned char *update;
13979         int numsurfacelist = 0;
13980         if (model == NULL)
13981                 return;
13982
13983         if (r_maxsurfacelist < model->num_surfaces)
13984         {
13985                 r_maxsurfacelist = model->num_surfaces;
13986                 if (r_surfacelist)
13987                         Mem_Free((msurface_t **)r_surfacelist);
13988                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13989         }
13990
13991         // if the model is static it doesn't matter what value we give for
13992         // wantnormals and wanttangents, so this logic uses only rules applicable
13993         // to a model, knowing that they are meaningless otherwise
13994         if (ent == r_refdef.scene.worldentity)
13995                 RSurf_ActiveWorldEntity();
13996         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13997                 RSurf_ActiveModelEntity(ent, false, false, false);
13998         else if (prepass)
13999                 RSurf_ActiveModelEntity(ent, true, true, true);
14000         else if (depthonly)
14001         {
14002                 switch (vid.renderpath)
14003                 {
14004                 case RENDERPATH_GL20:
14005                 case RENDERPATH_CGGL:
14006                 case RENDERPATH_D3D9:
14007                 case RENDERPATH_D3D10:
14008                 case RENDERPATH_D3D11:
14009                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14010                         break;
14011                 case RENDERPATH_GL13:
14012                 case RENDERPATH_GL11:
14013                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14014                         break;
14015                 }
14016         }
14017         else
14018         {
14019                 switch (vid.renderpath)
14020                 {
14021                 case RENDERPATH_GL20:
14022                 case RENDERPATH_CGGL:
14023                 case RENDERPATH_D3D9:
14024                 case RENDERPATH_D3D10:
14025                 case RENDERPATH_D3D11:
14026                         RSurf_ActiveModelEntity(ent, true, true, false);
14027                         break;
14028                 case RENDERPATH_GL13:
14029                 case RENDERPATH_GL11:
14030                         RSurf_ActiveModelEntity(ent, true, false, false);
14031                         break;
14032                 }
14033         }
14034
14035         surfaces = model->data_surfaces;
14036         update = model->brushq1.lightmapupdateflags;
14037
14038         // update light styles
14039         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14040         {
14041                 model_brush_lightstyleinfo_t *style;
14042                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14043                 {
14044                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14045                         {
14046                                 int *list = style->surfacelist;
14047                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14048                                 for (j = 0;j < style->numsurfaces;j++)
14049                                         update[list[j]] = true;
14050                         }
14051                 }
14052         }
14053
14054         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14055
14056         if (debug)
14057         {
14058                 R_DrawDebugModel();
14059                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14060                 return;
14061         }
14062
14063         rsurface.lightmaptexture = NULL;
14064         rsurface.deluxemaptexture = NULL;
14065         rsurface.uselightmaptexture = false;
14066         rsurface.texture = NULL;
14067         rsurface.rtlight = NULL;
14068         numsurfacelist = 0;
14069         // add visible surfaces to draw list
14070         for (i = 0;i < model->nummodelsurfaces;i++)
14071                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14072         // don't do anything if there were no surfaces
14073         if (!numsurfacelist)
14074         {
14075                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14076                 return;
14077         }
14078         // update lightmaps if needed
14079         if (update)
14080         {
14081                 int updated = 0;
14082                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14083                 {
14084                         if (update[j])
14085                         {
14086                                 updated++;
14087                                 R_BuildLightMap(ent, surfaces + j);
14088                         }
14089                 }
14090         }
14091         if (update)
14092                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14093                         if (update[j])
14094                                 R_BuildLightMap(ent, surfaces + j);
14095         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14096         GL_AlphaTest(false);
14097
14098         // add to stats if desired
14099         if (r_speeds.integer && !skysurfaces && !depthonly)
14100         {
14101                 r_refdef.stats.entities_surfaces += numsurfacelist;
14102                 for (j = 0;j < numsurfacelist;j++)
14103                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14104         }
14105
14106         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14107 }
14108
14109 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14110 {
14111         static texture_t texture;
14112         static msurface_t surface;
14113         const msurface_t *surfacelist = &surface;
14114
14115         // fake enough texture and surface state to render this geometry
14116
14117         texture.update_lastrenderframe = -1; // regenerate this texture
14118         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14119         texture.currentskinframe = skinframe;
14120         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14121         texture.offsetmapping = OFFSETMAPPING_OFF;
14122         texture.offsetscale = 1;
14123         texture.specularscalemod = 1;
14124         texture.specularpowermod = 1;
14125
14126         surface.texture = &texture;
14127         surface.num_triangles = numtriangles;
14128         surface.num_firsttriangle = firsttriangle;
14129         surface.num_vertices = numvertices;
14130         surface.num_firstvertex = firstvertex;
14131
14132         // now render it
14133         rsurface.texture = R_GetCurrentTexture(surface.texture);
14134         rsurface.lightmaptexture = NULL;
14135         rsurface.deluxemaptexture = NULL;
14136         rsurface.uselightmaptexture = false;
14137         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14138 }
14139
14140 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)
14141 {
14142         static msurface_t surface;
14143         const msurface_t *surfacelist = &surface;
14144
14145         // fake enough texture and surface state to render this geometry
14146
14147         surface.texture = texture;
14148         surface.num_triangles = numtriangles;
14149         surface.num_firsttriangle = firsttriangle;
14150         surface.num_vertices = numvertices;
14151         surface.num_firstvertex = firstvertex;
14152
14153         // now render it
14154         rsurface.texture = R_GetCurrentTexture(surface.texture);
14155         rsurface.lightmaptexture = NULL;
14156         rsurface.deluxemaptexture = NULL;
14157         rsurface.uselightmaptexture = false;
14158         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14159 }