]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
Forgot to put back the paranoid code
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
146
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
170
171 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
172
173 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
502         }
503 }
504
505 static void R_BuildFogHeightTexture(void)
506 {
507         unsigned char *inpixels;
508         int size;
509         int x;
510         int y;
511         int j;
512         float c[4];
513         float f;
514         inpixels = NULL;
515         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516         if (r_refdef.fogheighttexturename[0])
517                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
518         if (!inpixels)
519         {
520                 r_refdef.fog_height_tablesize = 0;
521                 if (r_texture_fogheighttexture)
522                         R_FreeTexture(r_texture_fogheighttexture);
523                 r_texture_fogheighttexture = NULL;
524                 if (r_refdef.fog_height_table2d)
525                         Mem_Free(r_refdef.fog_height_table2d);
526                 r_refdef.fog_height_table2d = NULL;
527                 if (r_refdef.fog_height_table1d)
528                         Mem_Free(r_refdef.fog_height_table1d);
529                 r_refdef.fog_height_table1d = NULL;
530                 return;
531         }
532         size = image_width;
533         r_refdef.fog_height_tablesize = size;
534         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
537         Mem_Free(inpixels);
538         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
539         // average fog color table accounting for every fog layer between a point
540         // and the camera.  (Note: attenuation is handled separately!)
541         for (y = 0;y < size;y++)
542         {
543                 for (x = 0;x < size;x++)
544                 {
545                         Vector4Clear(c);
546                         f = 0;
547                         if (x < y)
548                         {
549                                 for (j = x;j <= y;j++)
550                                 {
551                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
552                                         f++;
553                                 }
554                         }
555                         else
556                         {
557                                 for (j = x;j >= y;j--)
558                                 {
559                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
560                                         f++;
561                                 }
562                         }
563                         f = 1.0f / f;
564                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
568                 }
569         }
570         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
571 }
572
573 //=======================================================================================================================================================
574
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "#   extension GL_EXT_gpu_shader4 : enable\n"
593 "# endif\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "#   extension GL_ARB_texture_gather : enable\n"
596 "# else\n"
597 "#   ifdef GL_AMD_texture_texture4\n"
598 "#     extension GL_AMD_texture_texture4 : enable\n"
599 "#   endif\n"
600 "# endif\n"
601 "#endif\n"
602 "\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
605 "//#endif\n"
606 "\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
612 "//#else\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
617 "//#endif\n"
618 "\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
621 "#endif\n"
622 "\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
625 "void main(void)\n"
626 "{\n"
627 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
628 "}\n"
629 "#endif\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
631 "\n"
632 "\n"
633 "\n"
634 "\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
641 "}\n"
642 "#endif\n"
643 "\n"
644 "#ifdef FRAGMENT_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_FragColor = gl_Color;\n"
648 "}\n"
649 "#endif\n"
650 "#else // !MODE_SHOWDEPTH\n"
651 "\n"
652 "\n"
653 "\n"
654 "\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
658 "\n"
659 "#ifdef VERTEX_SHADER\n"
660 "void main(void)\n"
661 "{\n"
662 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USEBLOOM\n"
665 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
666 "#endif\n"
667 "}\n"
668 "#endif\n"
669 "\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
672 "#ifdef USEBLOOM\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
675 "#endif\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
678 "#endif\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
681 "#endif\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
684 "#endif\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
695 "#ifdef USEBLOOM\n"
696 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
697 "#endif\n"
698 "#ifdef USEVIEWTINT\n"
699 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
700 "#endif\n"
701 "\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
705 "       float sobel = 1.0;\n"
706 "       // vec2 ts = textureSize(Texture_First, 0);\n"
707 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 "       vec2 px = PixelSize;\n"
709 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
711 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
714 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
717 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
720 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
738 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
739 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USESATURATION\n"
744 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USEGAMMARAMPS\n"
751 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
754 "#endif\n"
755 "}\n"
756 "#endif\n"
757 "#else // !MODE_POSTPROCESS\n"
758 "\n"
759 "\n"
760 "\n"
761 "\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
765 "#endif\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
768 "#endif\n"
769 "#ifdef VERTEX_SHADER\n"
770 "void main(void)\n"
771 "{\n"
772 "       gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
775 "#endif\n"
776 "#ifdef USESPECULAR\n"
777 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
778 "#endif\n"
779 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
780 "}\n"
781 "#endif\n"
782 "\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
789 "#endif\n"
790 "\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
796 "#endif\n"
797 "\n"
798 "#ifdef USESPECULAR\n"
799 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 "       gl_FragColor *= tex2;\n"
802 "# endif\n"
803 "# ifdef USEGLOW\n"
804 "       gl_FragColor += tex2;\n"
805 "# endif\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
808 "# endif\n"
809 "#endif\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_GENERIC\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
820 "void main(void)\n"
821 "{\n"
822 "       gl_FrontColor = gl_Color;\n"
823 "       TexCoord = gl_MultiTexCoord0.xy;\n"
824 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
825 "}\n"
826 "#endif\n"
827 "\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
831 "\n"
832 "void main(void)\n"
833 "{\n"
834 "       int i;\n"
835 "       vec2 tc = TexCoord;\n"
836 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 "       tc += BloomBlur_Parameters.xy;\n"
838 "       for (i = 1;i < SAMPLES;i++)\n"
839 "       {\n"
840 "               color += texture2D(Texture_First, tc).rgb;\n"
841 "               tc += BloomBlur_Parameters.xy;\n"
842 "       }\n"
843 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
852 "\n"
853 "void main(void)\n"
854 "{\n"
855 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 "       ModelViewProjectionPosition = gl_Position;\n"
858 "}\n"
859 "#endif\n"
860 "\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
865 "\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
873 "\n"
874 "void main(void)\n"
875 "{\n"
876 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 "       // FIXME temporary hack to detect the case that the reflection\n"
881 "       // gets blackened at edges due to leaving the area that contains actual\n"
882 "       // content.\n"
883 "       // Remove this 'ack once we have a better way to stop this thing from\n"
884 "       // 'appening.\n"
885 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
891 "}\n"
892 "#endif\n"
893 "#else // !MODE_REFRACTION\n"
894 "\n"
895 "\n"
896 "\n"
897 "\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
905 "\n"
906 "void main(void)\n"
907 "{\n"
908 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 "       // FIXME temporary hack to detect the case that the reflection\n"
939 "       // gets blackened at edges due to leaving the area that contains actual\n"
940 "       // content.\n"
941 "       // Remove this 'ack once we have a better way to stop this thing from\n"
942 "       // 'appening.\n"
943 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
955 "}\n"
956 "#endif\n"
957 "#else // !MODE_WATER\n"
958 "\n"
959 "\n"
960 "\n"
961 "\n"
962 "// common definitions between vertex shader and fragment shader:\n"
963 "\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
967 "#endif\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
970 "#endif\n"
971 "\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
974 "#endif\n"
975 "\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
982 "#endif\n"
983 "#ifdef USEFOG\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
985 "#endif\n"
986 "\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
991 "#endif\n"
992 "\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
995 "#endif\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1003 "#endif\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1007 "#endif\n"
1008 "uniform vec4 FogPlane;\n"
1009 "\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1012 "#endif\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "\n"
1018 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1019 "\n"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1022 "\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1026 "#ifdef USEGLOW\n"
1027 "uniform sampler2D Texture_Glow;\n"
1028 "#endif\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1033 "#ifdef USEGLOW\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1035 "#endif\n"
1036 "#endif\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1040 "#endif\n"
1041 "#ifdef USEFOG\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1044 "#endif\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1046 "#endif\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1049 "#endif\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1052 "#endif\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1055 "#endif\n"
1056 "\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1060 "#endif\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1064 "#endif\n"
1065 "\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1069 "\n"
1070 "#ifdef USEFOG\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1075 "{\n"
1076 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1078 "       float fogfrac;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 "       fogfrac = fogheightpixel.a;\n"
1082 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1083 "#else\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1086 "# else\n"
1087 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1088 "# endif\n"
1089 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1090 "#endif\n"
1091 "}\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1097 "{\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 "       // 14 sample relief mapping: linear search and then binary search\n"
1100 "       // this basically steps forward a small amount repeatedly until it finds\n"
1101 "       // itself inside solid, then jitters forward and back using decreasing\n"
1102 "       // amounts to find the impact\n"
1103 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 "       vec3 RT = vec3(TexCoord, 1);\n"
1107 "       OffsetVector *= 0.1;\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1118 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1119 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1120 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1121 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1122 "       return RT.xy;\n"
1123 "#else\n"
1124 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 "       // this basically moves forward the full distance, and then backs up based\n"
1126 "       // on height of samples\n"
1127 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 "       TexCoord += OffsetVector;\n"
1131 "       OffsetVector *= 0.333;\n"
1132 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 "       return TexCoord;\n"
1136 "#endif\n"
1137 "}\n"
1138 "#endif // USEOFFSETMAPPING\n"
1139 "\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1143 "#endif\n"
1144 "\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1146 "\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1150 "# else\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1152 "# endif\n"
1153 "#endif\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1157 "#endif\n"
1158 "\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1162 "#endif\n"
1163 "\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1167 "# else\n"
1168 "#  ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1175 "}\n"
1176 "#  else\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 adir = abs(dir);\n"
1180 "       float ma = adir.z;\n"
1181 "       vec4 proj = vec4(dir, 2.5);\n"
1182 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1186 "}\n"
1187 "#  endif\n"
1188 "# endif\n"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1190 "\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1193 "{\n"
1194 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1195 "       float f;\n"
1196 "\n"
1197 "#  ifdef USESHADOWSAMPLER\n"
1198 "#    ifdef USESHADOWMAPPCF\n"
1199 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1200 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1202 "#    else\n"
1203 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1204 "#    endif\n"
1205 "#  else\n"
1206 "#    ifdef USESHADOWMAPPCF\n"
1207 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "#      ifdef GL_ARB_texture_gather\n"
1209 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1210 "#      else\n"
1211 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1212 "#      endif\n"
1213 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "#      if USESHADOWMAPPCF > 1\n"
1215 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1219 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1220 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1221 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1222 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1223 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1224 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 "       locols.yz += group2.ab;\n"
1227 "       hicols.yz += group8.rg;\n"
1228 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 "                               mix(locols, hicols, offset.y);\n"
1231 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 "       f = dot(cols, vec4(1.0/25.0));\n"
1234 "#      else\n"
1235 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1238 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1239 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1242 "#      endif\n"
1243 "#     else\n"
1244 "#      ifdef GL_EXT_gpu_shader4\n"
1245 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1248 "#      endif\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 "       center *= ShadowMap_TextureScale;\n"
1252 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1253 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1254 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1255 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1256 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1258 "#      else\n"
1259 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1262 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1263 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1265 "#      endif\n"
1266 "#     endif\n"
1267 "#    else\n"
1268 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1269 "#    endif\n"
1270 "#  endif\n"
1271 "#  ifdef USESHADOWMAPORTHO\n"
1272 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1273 "#  else\n"
1274 "       return f;\n"
1275 "#  endif\n"
1276 "}\n"
1277 "# endif\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1280 "\n"
1281 "\n"
1282 "\n"
1283 "\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1289 "#endif\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1291 "void main(void)\n"
1292 "{\n"
1293 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 "       gl_FrontColor = gl_Color;\n"
1296 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1297 "#endif\n"
1298 "\n"
1299 "       // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1305 "#endif\n"
1306 "\n"
1307 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1311 "}\n"
1312 "#endif // VERTEX_SHADER\n"
1313 "\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1315 "void main(void)\n"
1316 "{\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 "       // apply offsetmapping\n"
1319 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1321 "#endif\n"
1322 "\n"
1323 "#ifdef USEALPHAKILL\n"
1324 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "               discard;\n"
1326 "#endif\n"
1327 "\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1333 "#endif\n"
1334 "\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1338 "#else\n"
1339 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1341 "#endif\n"
1342 "\n"
1343 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1344 "}\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1347 "\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1354 "void main(void)\n"
1355 "{\n"
1356 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1358 "}\n"
1359 "#endif // VERTEX_SHADER\n"
1360 "\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1370 "#endif\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       // calculate viewspace pixel position\n"
1375 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1376 "       vec3 position;\n"
1377 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 "       // decode viewspace pixel normal\n"
1380 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 "       // surfacenormal = pixel normal in viewspace\n"
1383 "       // LightVector = pixel to light in viewspace\n"
1384 "       // CubeVector = position in lightspace\n"
1385 "       // eyevector = pixel to view in viewspace\n"
1386 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 "       // calculate diffuse shading\n"
1390 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1392 "#endif\n"
1393 "#ifdef USESPECULAR\n"
1394 "       // calculate directional shading\n"
1395 "       vec3 eyevector = position * -1.0;\n"
1396 "#  ifdef USEEXACTSPECULARMATH\n"
1397 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1398 "#  else\n"
1399 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1401 "#  endif\n"
1402 "#endif\n"
1403 "\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 "       fade *= ShadowMapCompare(CubeVector);\n"
1406 "#endif\n"
1407 "\n"
1408 "#ifdef USEDIFFUSE\n"
1409 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1410 "#else\n"
1411 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1412 "#endif\n"
1413 "#ifdef USESPECULAR\n"
1414 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1415 "#else\n"
1416 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1417 "#endif\n"
1418 "\n"
1419 "# ifdef USECUBEFILTER\n"
1420 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 "       gl_FragData[0].rgb *= cubecolor;\n"
1422 "       gl_FragData[1].rgb *= cubecolor;\n"
1423 "# endif\n"
1424 "}\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1427 "\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1435 "#endif\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1438 "#endif\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1441 "#endif\n"
1442 "void main(void)\n"
1443 "{\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 "       gl_FrontColor = gl_Color;\n"
1446 "#endif\n"
1447 "       // copy the surface texcoord\n"
1448 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1451 "#endif\n"
1452 "#ifdef USELIGHTMAP\n"
1453 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "       // transform vertex position into light attenuation/cubemap space\n"
1458 "       // (-1 to +1 across the light box)\n"
1459 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1460 "\n"
1461 "# ifdef USEDIFFUSE\n"
1462 "       // transform unnormalized light direction into tangent space\n"
1463 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 "       //  normalize it per pixel)\n"
1465 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1476 "#endif\n"
1477 "\n"
1478 "       // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef USEFOG\n"
1487 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1489 "#endif\n"
1490 "\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1493 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1494 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1495 "#endif\n"
1496 "\n"
1497 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1499 "\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef USEREFLECTION\n"
1505 "       ModelViewProjectionPosition = gl_Position;\n"
1506 "#endif\n"
1507 "}\n"
1508 "#endif // VERTEX_SHADER\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1518 "#endif\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1523 "#ifdef USEGLOW\n"
1524 "uniform myhalf3 Color_Glow;\n"
1525 "#endif\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1532 "#endif\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1537 "#endif\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1540 "#endif\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1543 "#endif\n"
1544 "void main(void)\n"
1545 "{\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 "       // apply offsetmapping\n"
1548 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1550 "#endif\n"
1551 "\n"
1552 "       // combine the diffuse textures (base, pants, shirt)\n"
1553 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 "       if (color.a < 0.5)\n"
1556 "               discard;\n"
1557 "#endif\n"
1558 "       color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1561 "#endif\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1567 "       color.a = 1.0;\n"
1568 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1569 "#endif\n"
1570 "\n"
1571 "       // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1574 "#else\n"
1575 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1576 "#endif\n"
1577 "\n"
1578 "       // get the material colors\n"
1579 "       myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1583 "# else\n"
1584 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1585 "# endif\n"
1586 "#endif\n"
1587 "\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1593 "#endif\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 "       // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1607 "#else\n"
1608 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1610 "#endif\n"
1611 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1612 "#endif\n"
1613 "#else\n"
1614 "       color.rgb = diffusetex * Color_Ambient;\n"
1615 "#endif\n"
1616 "       color.rgb *= LightColor;\n"
1617 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1620 "#endif\n"
1621 "# ifdef USECUBEFILTER\n"
1622 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1623 "# endif\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1630 "#define SHADING\n"
1631 "#ifdef USEDIFFUSE\n"
1632 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1633 "#endif\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1637 "#define SHADING\n"
1638 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 "       // convert modelspace light vector to tangentspace\n"
1642 "       myhalf3 lightnormal;\n"
1643 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1658 "#define SHADING\n"
1659 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1662 "#endif\n"
1663 "\n"
1664 "\n"
1665 "\n"
1666 "\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 "       color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "\n"
1680 "#ifdef SHADING\n"
1681 "# ifdef USEDIFFUSE\n"
1682 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "#  ifdef USESPECULAR\n"
1684 "#   ifdef USEEXACTSPECULARMATH\n"
1685 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1686 "#   else\n"
1687 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1689 "#   endif\n"
1690 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1691 "#  else\n"
1692 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1693 "#  endif\n"
1694 "# else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "# endif\n"
1697 "#endif\n"
1698 "\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1701 "#endif\n"
1702 "\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1707 "#endif\n"
1708 "\n"
1709 "#ifdef USEGLOW\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1712 "#else\n"
1713 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1714 "#endif\n"
1715 "#endif\n"
1716 "\n"
1717 "#ifdef USEFOG\n"
1718 "       color.rgb = FogVertex(color.rgb);\n"
1719 "#endif\n"
1720 "\n"
1721 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1722 "#ifdef USEREFLECTION\n"
1723 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 "       // FIXME temporary hack to detect the case that the reflection\n"
1728 "       // gets blackened at edges due to leaving the area that contains actual\n"
1729 "       // content.\n"
1730 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1731 "       // 'appening.\n"
1732 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1738 "#endif\n"
1739 "\n"
1740 "       gl_FragColor = vec4(color);\n"
1741 "}\n"
1742 "#endif // FRAGMENT_SHADER\n"
1743 "\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1753 ;
1754
1755 /*
1756 =========================================================================================================================================================
1757
1758
1759
1760 =========================================================================================================================================================
1761
1762
1763
1764 =========================================================================================================================================================
1765
1766
1767
1768 =========================================================================================================================================================
1769
1770
1771
1772 =========================================================================================================================================================
1773
1774
1775
1776 =========================================================================================================================================================
1777
1778
1779
1780 =========================================================================================================================================================
1781 */
1782
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1787 "\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1791 "#endif\n"
1792 "\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1794 "# define USEFOG\n"
1795 "#endif\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1798 "#endif\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1801 "#endif\n"
1802 "\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1804 "#ifdef HLSL\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1808 "#else\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1810 "#endif\n"
1811 "#endif\n"
1812 "\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1815 "void main\n"
1816 "(\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1821 ")\n"
1822 "{\n"
1823 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 "       Depth = gl_Position.z;\n"
1825 "}\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1829 "void main\n"
1830 "(\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1833 ")\n"
1834 "{\n"
1835 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1837 "       temp.yz -= floor(temp.yz);\n"
1838 "       gl_FragColor = temp;\n"
1839 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1840 "}\n"
1841 "#endif\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1843 "\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1849 "void main\n"
1850 "(\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1855 ")\n"
1856 "{\n"
1857 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1859 "}\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1863 "void main\n"
1864 "(\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_FragColor = gl_FrontColor;\n"
1870 "}\n"
1871 "#endif\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1873 "\n"
1874 "\n"
1875 "\n"
1876 "\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1878 "\n"
1879 "#ifdef VERTEX_SHADER\n"
1880 "void main\n"
1881 "(\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1889 ")\n"
1890 "{\n"
1891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1893 "#ifdef USEBLOOM\n"
1894 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1895 "#endif\n"
1896 "}\n"
1897 "#endif\n"
1898 "\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1900 "void main\n"
1901 "(\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1905 "#ifdef USEBLOOM\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1907 "#endif\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1910 "#endif\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1913 "#endif\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1916 "#endif\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1928 "#ifdef USEBLOOM\n"
1929 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1930 "#endif\n"
1931 "#ifdef USEVIEWTINT\n"
1932 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1933 "#endif\n"
1934 "\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1938 "       float sobel = 1.0;\n"
1939 "       // float2 ts = textureSize(Texture_First, 0);\n"
1940 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 "       float2 px = PixelSize;\n"
1942 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1944 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1947 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1950 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1953 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1971 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1972 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1974 "#endif\n"
1975 "\n"
1976 "#ifdef USESATURATION\n"
1977 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1981 "#endif\n"
1982 "\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1987 "#endif\n"
1988 "}\n"
1989 "#endif\n"
1990 "#else // !MODE_POSTPROCESS\n"
1991 "\n"
1992 "\n"
1993 "\n"
1994 "\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1997 "void main\n"
1998 "(\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "out float4 gl_FrontColor : COLOR,\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "out float2 TexCoord2 : TEXCOORD1\n"
2008 ")\n"
2009 "{\n"
2010 "#ifdef HLSL\n"
2011 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2012 "#else\n"
2013 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2014 "#endif\n"
2015 "#ifdef USEDIFFUSE\n"
2016 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2017 "#endif\n"
2018 "#ifdef USESPECULAR\n"
2019 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2020 "#endif\n"
2021 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2022 "}\n"
2023 "#endif\n"
2024 "\n"
2025 "#ifdef FRAGMENT_SHADER\n"
2026 "\n"
2027 "void main\n"
2028 "(\n"
2029 "float4 gl_FrontColor : COLOR0,\n"
2030 "float2 TexCoord1 : TEXCOORD0,\n"
2031 "float2 TexCoord2 : TEXCOORD1,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2034 "#endif\n"
2035 "#ifdef USESPECULAR\n"
2036 "uniform sampler Texture_Second : register(s1),\n"
2037 "#endif\n"
2038 "out float4 gl_FragColor : COLOR\n"
2039 ")\n"
2040 "{\n"
2041 "       gl_FragColor = gl_FrontColor;\n"
2042 "#ifdef USEDIFFUSE\n"
2043 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2044 "#endif\n"
2045 "\n"
2046 "#ifdef USESPECULAR\n"
2047 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2048 "# ifdef USECOLORMAPPING\n"
2049 "       gl_FragColor *= tex2;\n"
2050 "# endif\n"
2051 "# ifdef USEGLOW\n"
2052 "       gl_FragColor += tex2;\n"
2053 "# endif\n"
2054 "# ifdef USEVERTEXTEXTUREBLEND\n"
2055 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2056 "# endif\n"
2057 "#endif\n"
2058 "}\n"
2059 "#endif\n"
2060 "#else // !MODE_GENERIC\n"
2061 "\n"
2062 "\n"
2063 "\n"
2064 "\n"
2065 "#ifdef MODE_BLOOMBLUR\n"
2066 "#ifdef VERTEX_SHADER\n"
2067 "void main\n"
2068 "(\n"
2069 "float4 gl_Vertex : POSITION,\n"
2070 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2071 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2072 "out float4 gl_Position : POSITION,\n"
2073 "out float2 TexCoord : TEXCOORD0\n"
2074 ")\n"
2075 "{\n"
2076 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2077 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2078 "}\n"
2079 "#endif\n"
2080 "\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2082 "\n"
2083 "void main\n"
2084 "(\n"
2085 "float2 TexCoord : TEXCOORD0,\n"
2086 "uniform sampler Texture_First : register(s0),\n"
2087 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       int i;\n"
2092 "       float2 tc = TexCoord;\n"
2093 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2094 "       tc += BloomBlur_Parameters.xy;\n"
2095 "       for (i = 1;i < SAMPLES;i++)\n"
2096 "       {\n"
2097 "               color += tex2D(Texture_First, tc).rgb;\n"
2098 "               tc += BloomBlur_Parameters.xy;\n"
2099 "       }\n"
2100 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2101 "}\n"
2102 "#endif\n"
2103 "#else // !MODE_BLOOMBLUR\n"
2104 "#ifdef MODE_REFRACTION\n"
2105 "#ifdef VERTEX_SHADER\n"
2106 "void main\n"
2107 "(\n"
2108 "float4 gl_Vertex : POSITION,\n"
2109 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2110 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2111 "uniform float4x4 TexMatrix : register(c0),\n"
2112 "uniform float3 EyePosition : register(c24),\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0,\n"
2115 "out float3 EyeVector : TEXCOORD1,\n"
2116 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2117 ")\n"
2118 "{\n"
2119 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2120 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 "       ModelViewProjectionPosition = gl_Position;\n"
2122 "}\n"
2123 "#endif\n"
2124 "\n"
2125 "#ifdef FRAGMENT_SHADER\n"
2126 "void main\n"
2127 "(\n"
2128 "float2 TexCoord : TEXCOORD0,\n"
2129 "float3 EyeVector : TEXCOORD1,\n"
2130 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2131 "uniform sampler Texture_Normal : register(s0),\n"
2132 "uniform sampler Texture_Refraction : register(s3),\n"
2133 "uniform sampler Texture_Reflection : register(s7),\n"
2134 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2135 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2136 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2137 "uniform float4 RefractColor : register(c29),\n"
2138 "out float4 gl_FragColor : COLOR\n"
2139 ")\n"
2140 "{\n"
2141 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2142 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2143 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2144 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2145 "       // FIXME temporary hack to detect the case that the reflection\n"
2146 "       // gets blackened at edges due to leaving the area that contains actual\n"
2147 "       // content.\n"
2148 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2149 "       // 'appening.\n"
2150 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2151 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2152 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2153 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2154 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2155 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2156 "}\n"
2157 "#endif\n"
2158 "#else // !MODE_REFRACTION\n"
2159 "\n"
2160 "\n"
2161 "\n"
2162 "\n"
2163 "#ifdef MODE_WATER\n"
2164 "#ifdef VERTEX_SHADER\n"
2165 "\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2172 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2173 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2174 "uniform float4x4 TexMatrix : register(c0),\n"
2175 "uniform float3 EyePosition : register(c24),\n"
2176 "out float4 gl_Position : POSITION,\n"
2177 "out float2 TexCoord : TEXCOORD0,\n"
2178 "out float3 EyeVector : TEXCOORD1,\n"
2179 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2180 ")\n"
2181 "{\n"
2182 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2183 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2184 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2185 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2186 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2187 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 "       ModelViewProjectionPosition = gl_Position;\n"
2189 "}\n"
2190 "#endif\n"
2191 "\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2193 "void main\n"
2194 "(\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler Texture_Normal : register(s0),\n"
2199 "uniform sampler Texture_Refraction : register(s3),\n"
2200 "uniform sampler Texture_Reflection : register(s7),\n"
2201 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2202 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2203 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2204 "uniform float4 RefractColor : register(c29),\n"
2205 "uniform float4 ReflectColor : register(c26),\n"
2206 "uniform float ReflectFactor : register(c27),\n"
2207 "uniform float ReflectOffset : register(c28),\n"
2208 "out float4 gl_FragColor : COLOR\n"
2209 ")\n"
2210 "{\n"
2211 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2212 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2213 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2214 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2215 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2216 "       // FIXME temporary hack to detect the case that the reflection\n"
2217 "       // gets blackened at edges due to leaving the area that contains actual\n"
2218 "       // content.\n"
2219 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2220 "       // 'appening.\n"
2221 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2222 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2223 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2224 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2225 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2226 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2227 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2228 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2229 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2230 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2231 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2232 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2233 "}\n"
2234 "#endif\n"
2235 "#else // !MODE_WATER\n"
2236 "\n"
2237 "\n"
2238 "\n"
2239 "\n"
2240 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2241 "\n"
2242 "// fragment shader specific:\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2244 "\n"
2245 "#ifdef USEFOG\n"
2246 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2247 "{\n"
2248 "       float fogfrac;\n"
2249 "#ifdef USEFOGHEIGHTTEXTURE\n"
2250 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2251 "       fogfrac = fogheightpixel.a;\n"
2252 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2253 "#else\n"
2254 "# ifdef USEFOGOUTSIDE\n"
2255 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2256 "# else\n"
2257 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2258 "# endif\n"
2259 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2260 "#endif\n"
2261 "}\n"
2262 "#endif\n"
2263 "\n"
2264 "#ifdef USEOFFSETMAPPING\n"
2265 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2266 "{\n"
2267 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2268 "       // 14 sample relief mapping: linear search and then binary search\n"
2269 "       // this basically steps forward a small amount repeatedly until it finds\n"
2270 "       // itself inside solid, then jitters forward and back using decreasing\n"
2271 "       // amounts to find the impact\n"
2272 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2273 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2274 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2275 "       float3 RT = float3(TexCoord, 1);\n"
2276 "       OffsetVector *= 0.1;\n"
2277 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2278 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2279 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2280 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2281 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2287 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2288 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2289 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2290 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2291 "       return RT.xy;\n"
2292 "#else\n"
2293 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2294 "       // this basically moves forward the full distance, and then backs up based\n"
2295 "       // on height of samples\n"
2296 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2297 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2298 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2299 "       TexCoord += OffsetVector;\n"
2300 "       OffsetVector *= 0.333;\n"
2301 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2302 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2303 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2304 "       return TexCoord;\n"
2305 "#endif\n"
2306 "}\n"
2307 "#endif // USEOFFSETMAPPING\n"
2308 "\n"
2309 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2310 "#if defined(USESHADOWMAP2D)\n"
2311 "# ifdef USESHADOWMAPORTHO\n"
2312 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2313 "# else\n"
2314 "#  ifdef USESHADOWMAPVSDCT\n"
2315 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2316 "{\n"
2317 "       float3 adir = abs(dir);\n"
2318 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2319 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2320 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2321 "}\n"
2322 "#  else\n"
2323 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2324 "{\n"
2325 "       float3 adir = abs(dir);\n"
2326 "       float ma = adir.z;\n"
2327 "       float4 proj = float4(dir, 2.5);\n"
2328 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2329 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2330 "#ifdef HLSL\n"
2331 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2332 "#else\n"
2333 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2334 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2335 "#endif\n"
2336 "}\n"
2337 "#  endif\n"
2338 "# endif\n"
2339 "#endif // defined(USESHADOWMAP2D)\n"
2340 "\n"
2341 "# ifdef USESHADOWMAP2D\n"
2342 "#ifdef USESHADOWMAPVSDCT\n"
2343 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2344 "#else\n"
2345 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2346 "#endif\n"
2347 "{\n"
2348 "#ifdef USESHADOWMAPVSDCT\n"
2349 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2350 "#else\n"
2351 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2352 "#endif\n"
2353 "       float f;\n"
2354 "\n"
2355 "#  ifdef USESHADOWSAMPLER\n"
2356 "#    ifdef USESHADOWMAPPCF\n"
2357 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2358 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2359 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2360 "#    else\n"
2361 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2362 "#    endif\n"
2363 "#  else\n"
2364 "#    ifdef USESHADOWMAPPCF\n"
2365 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2366 "#      ifdef GL_ARB_texture_gather\n"
2367 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2368 "#      else\n"
2369 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2370 "#      endif\n"
2371 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2372 "#      if USESHADOWMAPPCF > 1\n"
2373 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2374 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2375 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2376 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2377 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2378 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2379 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2380 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2381 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2382 "       float4 locols = float4(group1.ab, group3.ab);\n"
2383 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2384 "       locols.yz += group2.ab;\n"
2385 "       hicols.yz += group8.rg;\n"
2386 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2387 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2388 "                               lerp(locols, hicols, offset.y);\n"
2389 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2390 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2391 "       f = dot(cols, float4(1.0/25.0));\n"
2392 "#      else\n"
2393 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2394 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2395 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2396 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2397 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2398 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2399 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2400 "#      endif\n"
2401 "#     else\n"
2402 "#      ifdef GL_EXT_gpu_shader4\n"
2403 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2404 "#      else\n"
2405 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2406 "#      endif\n"
2407 "#      if USESHADOWMAPPCF > 1\n"
2408 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2409 "       center *= ShadowMap_TextureScale;\n"
2410 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2411 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2412 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2413 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2414 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2415 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2416 "#      else\n"
2417 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2418 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2419 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2420 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2421 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2422 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2423 "#      endif\n"
2424 "#     endif\n"
2425 "#    else\n"
2426 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2427 "#    endif\n"
2428 "#  endif\n"
2429 "#  ifdef USESHADOWMAPORTHO\n"
2430 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2431 "#  else\n"
2432 "       return f;\n"
2433 "#  endif\n"
2434 "}\n"
2435 "# endif\n"
2436 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2437 "#endif // FRAGMENT_SHADER\n"
2438 "\n"
2439 "\n"
2440 "\n"
2441 "\n"
2442 "#ifdef MODE_DEFERREDGEOMETRY\n"
2443 "#ifdef VERTEX_SHADER\n"
2444 "void main\n"
2445 "(\n"
2446 "float4 gl_Vertex : POSITION,\n"
2447 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "float4 gl_Color : COLOR0,\n"
2450 "#endif\n"
2451 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2452 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2453 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2454 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2455 "uniform float4x4 TexMatrix : register(c0),\n"
2456 "#ifdef USEVERTEXTEXTUREBLEND\n"
2457 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2458 "#endif\n"
2459 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2460 "#ifdef USEOFFSETMAPPING\n"
2461 "uniform float3 EyePosition : register(c24),\n"
2462 "#endif\n"
2463 "out float4 gl_Position : POSITION,\n"
2464 "out float4 gl_FrontColor : COLOR,\n"
2465 "out float4 TexCoordBoth : TEXCOORD0,\n"
2466 "#ifdef USEOFFSETMAPPING\n"
2467 "out float3 EyeVector : TEXCOORD2,\n"
2468 "#endif\n"
2469 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2470 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2471 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2472 ")\n"
2473 "{\n"
2474 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2476 "#ifdef HLSL\n"
2477 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2478 "#else\n"
2479 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2480 "#endif\n"
2481 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2482 "#endif\n"
2483 "\n"
2484 "       // transform unnormalized eye direction into tangent space\n"
2485 "#ifdef USEOFFSETMAPPING\n"
2486 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2487 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2488 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2489 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2490 "#endif\n"
2491 "\n"
2492 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2493 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2494 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2496 "       VectorR.w = gl_Position.z;\n"
2497 "}\n"
2498 "#endif // VERTEX_SHADER\n"
2499 "\n"
2500 "#ifdef FRAGMENT_SHADER\n"
2501 "void main\n"
2502 "(\n"
2503 "float4 TexCoordBoth : TEXCOORD0,\n"
2504 "float3 EyeVector : TEXCOORD2,\n"
2505 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2506 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2507 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2508 "uniform sampler Texture_Normal : register(s0),\n"
2509 "#ifdef USEALPHAKILL\n"
2510 "uniform sampler Texture_Color : register(s1),\n"
2511 "#endif\n"
2512 "uniform sampler Texture_Gloss : register(s2),\n"
2513 "#ifdef USEVERTEXTEXTUREBLEND\n"
2514 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2515 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2516 "#endif\n"
2517 "#ifdef USEOFFSETMAPPING\n"
2518 "uniform float OffsetMapping_Scale : register(c24),\n"
2519 "#endif\n"
2520 "uniform half SpecularPower : register(c36),\n"
2521 "#ifdef HLSL\n"
2522 "out float4 gl_FragData0 : COLOR0,\n"
2523 "out float4 gl_FragData1 : COLOR1\n"
2524 "#else\n"
2525 "out float4 gl_FragColor : COLOR\n"
2526 "#endif\n"
2527 ")\n"
2528 "{\n"
2529 "       float2 TexCoord = TexCoordBoth.xy;\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "       // apply offsetmapping\n"
2532 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2533 "#define TexCoord TexCoordOffset\n"
2534 "#endif\n"
2535 "\n"
2536 "#ifdef USEALPHAKILL\n"
2537 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2538 "               discard;\n"
2539 "#endif\n"
2540 "\n"
2541 "#ifdef USEVERTEXTEXTUREBLEND\n"
2542 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2543 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2544 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2545 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2546 "#endif\n"
2547 "\n"
2548 "#ifdef USEVERTEXTEXTUREBLEND\n"
2549 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2550 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2551 "#else\n"
2552 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2553 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2554 "#endif\n"
2555 "\n"
2556 "#ifdef HLSL\n"
2557 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2558 "       float Depth = VectorR.w / 256.0;\n"
2559 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2560 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2561 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2562 "       gl_FragData1 = depthcolor;\n"
2563 "#else\n"
2564 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2565 "#endif\n"
2566 "}\n"
2567 "#endif // FRAGMENT_SHADER\n"
2568 "#else // !MODE_DEFERREDGEOMETRY\n"
2569 "\n"
2570 "\n"
2571 "\n"
2572 "\n"
2573 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2574 "#ifdef VERTEX_SHADER\n"
2575 "void main\n"
2576 "(\n"
2577 "float4 gl_Vertex : POSITION,\n"
2578 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2579 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2580 "out float4 gl_Position : POSITION,\n"
2581 "out float4 ModelViewPosition : TEXCOORD0\n"
2582 ")\n"
2583 "{\n"
2584 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2585 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2586 "}\n"
2587 "#endif // VERTEX_SHADER\n"
2588 "\n"
2589 "#ifdef FRAGMENT_SHADER\n"
2590 "void main\n"
2591 "(\n"
2592 "#ifdef HLSL\n"
2593 "float2 Pixel : VPOS,\n"
2594 "#else\n"
2595 "float2 Pixel : WPOS,\n"
2596 "#endif\n"
2597 "float4 ModelViewPosition : TEXCOORD0,\n"
2598 "uniform float4x4 ViewToLight : register(c44),\n"
2599 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2600 "uniform float3 LightPosition : register(c23),\n"
2601 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2602 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2603 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2604 "#ifdef USESPECULAR\n"
2605 "uniform half3 DeferredColor_Specular : register(c11),\n"
2606 "uniform half SpecularPower : register(c36),\n"
2607 "#endif\n"
2608 "uniform sampler Texture_Attenuation : register(s9),\n"
2609 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2610 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2611 "\n"
2612 "#ifdef USECUBEFILTER\n"
2613 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2614 "#endif\n"
2615 "\n"
2616 "#ifdef USESHADOWMAP2D\n"
2617 "# ifdef USESHADOWSAMPLER\n"
2618 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2619 "# else\n"
2620 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2621 "# endif\n"
2622 "#endif\n"
2623 "\n"
2624 "#ifdef USESHADOWMAPVSDCT\n"
2625 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2626 "#endif\n"
2627 "\n"
2628 "#if defined(USESHADOWMAP2D)\n"
2629 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2630 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2631 "#endif\n"
2632 "\n"
2633 "out float4 gl_FragData0 : COLOR0,\n"
2634 "out float4 gl_FragData1 : COLOR1\n"
2635 ")\n"
2636 "{\n"
2637 "       // calculate viewspace pixel position\n"
2638 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2639 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2640 "       float3 position;\n"
2641 "#ifdef HLSL\n"
2642 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2643 "#else\n"
2644 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2645 "#endif\n"
2646 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2647 "       // decode viewspace pixel normal\n"
2648 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2649 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2650 "       // surfacenormal = pixel normal in viewspace\n"
2651 "       // LightVector = pixel to light in viewspace\n"
2652 "       // CubeVector = position in lightspace\n"
2653 "       // eyevector = pixel to view in viewspace\n"
2654 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2655 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2656 "#ifdef USEDIFFUSE\n"
2657 "       // calculate diffuse shading\n"
2658 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2659 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2660 "#endif\n"
2661 "#ifdef USESPECULAR\n"
2662 "       // calculate directional shading\n"
2663 "       float3 eyevector = position * -1.0;\n"
2664 "#  ifdef USEEXACTSPECULARMATH\n"
2665 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2666 "#  else\n"
2667 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2668 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2669 "#  endif\n"
2670 "#endif\n"
2671 "\n"
2672 "#if defined(USESHADOWMAP2D)\n"
2673 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2674 "#ifdef USESHADOWMAPVSDCT\n"
2675 ", Texture_CubeProjection\n"
2676 "#endif\n"
2677 "       ));\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USEDIFFUSE\n"
2681 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2682 "#else\n"
2683 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2684 "#endif\n"
2685 "#ifdef USESPECULAR\n"
2686 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2687 "#else\n"
2688 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2689 "#endif\n"
2690 "\n"
2691 "# ifdef USECUBEFILTER\n"
2692 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2693 "       gl_FragData0.rgb *= cubecolor;\n"
2694 "       gl_FragData1.rgb *= cubecolor;\n"
2695 "# endif\n"
2696 "}\n"
2697 "#endif // FRAGMENT_SHADER\n"
2698 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2699 "\n"
2700 "\n"
2701 "\n"
2702 "\n"
2703 "#ifdef VERTEX_SHADER\n"
2704 "void main\n"
2705 "(\n"
2706 "float4 gl_Vertex : POSITION,\n"
2707 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2708 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2709 "float4 gl_Color : COLOR0,\n"
2710 "#endif\n"
2711 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2712 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2713 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2714 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2715 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2716 "\n"
2717 "uniform float3 EyePosition : register(c24),\n"
2718 "uniform float4x4 TexMatrix : register(c0),\n"
2719 "#ifdef USEVERTEXTEXTUREBLEND\n"
2720 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2721 "#endif\n"
2722 "#ifdef MODE_LIGHTSOURCE\n"
2723 "uniform float4x4 ModelToLight : register(c20),\n"
2724 "#endif\n"
2725 "#ifdef MODE_LIGHTSOURCE\n"
2726 "uniform float3 LightPosition : register(c27),\n"
2727 "#endif\n"
2728 "#ifdef MODE_LIGHTDIRECTION\n"
2729 "uniform float3 LightDir : register(c26),\n"
2730 "#endif\n"
2731 "uniform float4 FogPlane : register(c25),\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "uniform float3 LightPosition : register(c27),\n"
2734 "#endif\n"
2735 "#ifdef USESHADOWMAPORTHO\n"
2736 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2737 "#endif\n"
2738 "\n"
2739 "out float4 gl_FrontColor : COLOR,\n"
2740 "out float4 TexCoordBoth : TEXCOORD0,\n"
2741 "#ifdef USELIGHTMAP\n"
2742 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2743 "#endif\n"
2744 "#ifdef USEEYEVECTOR\n"
2745 "out float3 EyeVector : TEXCOORD2,\n"
2746 "#endif\n"
2747 "#ifdef USEREFLECTION\n"
2748 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2749 "#endif\n"
2750 "#ifdef USEFOG\n"
2751 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2752 "#endif\n"
2753 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2754 "out float3 LightVector : TEXCOORD1,\n"
2755 "#endif\n"
2756 "#ifdef MODE_LIGHTSOURCE\n"
2757 "out float3 CubeVector : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2760 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2761 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2762 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2763 "#endif\n"
2764 "#ifdef USESHADOWMAPORTHO\n"
2765 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2766 "#endif\n"
2767 "out float4 gl_Position : POSITION\n"
2768 ")\n"
2769 "{\n"
2770 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2771 "#ifdef HLSL\n"
2772 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2773 "#else\n"
2774 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2775 "#endif\n"
2776 "#endif\n"
2777 "       // copy the surface texcoord\n"
2778 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2779 "#ifdef USEVERTEXTEXTUREBLEND\n"
2780 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2781 "#endif\n"
2782 "#ifdef USELIGHTMAP\n"
2783 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2784 "#endif\n"
2785 "\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "       // transform vertex position into light attenuation/cubemap space\n"
2788 "       // (-1 to +1 across the light box)\n"
2789 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2790 "\n"
2791 "# ifdef USEDIFFUSE\n"
2792 "       // transform unnormalized light direction into tangent space\n"
2793 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2794 "       //  normalize it per pixel)\n"
2795 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2796 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2797 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2798 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2799 "# endif\n"
2800 "#endif\n"
2801 "\n"
2802 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2803 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2804 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2805 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2806 "#endif\n"
2807 "\n"
2808 "       // transform unnormalized eye direction into tangent space\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2811 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2812 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2813 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2814 "#endif\n"
2815 "\n"
2816 "#ifdef USEFOG\n"
2817 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2818 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2822 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2823 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2824 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2825 "#endif\n"
2826 "\n"
2827 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2828 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2829 "\n"
2830 "#ifdef USESHADOWMAPORTHO\n"
2831 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2832 "#endif\n"
2833 "\n"
2834 "#ifdef USEREFLECTION\n"
2835 "       ModelViewProjectionPosition = gl_Position;\n"
2836 "#endif\n"
2837 "}\n"
2838 "#endif // VERTEX_SHADER\n"
2839 "\n"
2840 "\n"
2841 "\n"
2842 "\n"
2843 "#ifdef FRAGMENT_SHADER\n"
2844 "void main\n"
2845 "(\n"
2846 "#ifdef USEDEFERREDLIGHTMAP\n"
2847 "#ifdef HLSL\n"
2848 "float2 Pixel : VPOS,\n"
2849 "#else\n"
2850 "float2 Pixel : WPOS,\n"
2851 "#endif\n"
2852 "#endif\n"
2853 "float4 gl_FrontColor : COLOR,\n"
2854 "float4 TexCoordBoth : TEXCOORD0,\n"
2855 "#ifdef USELIGHTMAP\n"
2856 "float2 TexCoordLightmap : TEXCOORD1,\n"
2857 "#endif\n"
2858 "#ifdef USEEYEVECTOR\n"
2859 "float3 EyeVector : TEXCOORD2,\n"
2860 "#endif\n"
2861 "#ifdef USEREFLECTION\n"
2862 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2863 "#endif\n"
2864 "#ifdef USEFOG\n"
2865 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2866 "#endif\n"
2867 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2868 "float3 LightVector : TEXCOORD1,\n"
2869 "#endif\n"
2870 "#ifdef MODE_LIGHTSOURCE\n"
2871 "float3 CubeVector : TEXCOORD3,\n"
2872 "#endif\n"
2873 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2874 "float4 ModelViewPosition : TEXCOORD0,\n"
2875 "#endif\n"
2876 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2877 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2878 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2879 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2880 "#endif\n"
2881 "#ifdef USESHADOWMAPORTHO\n"
2882 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2883 "#endif\n"
2884 "\n"
2885 "uniform sampler Texture_Normal : register(s0),\n"
2886 "uniform sampler Texture_Color : register(s1),\n"
2887 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2888 "uniform sampler Texture_Gloss : register(s2),\n"
2889 "#endif\n"
2890 "#ifdef USEGLOW\n"
2891 "uniform sampler Texture_Glow : register(s3),\n"
2892 "#endif\n"
2893 "#ifdef USEVERTEXTEXTUREBLEND\n"
2894 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2895 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2896 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2897 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2898 "#endif\n"
2899 "#ifdef USEGLOW\n"
2900 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2901 "#endif\n"
2902 "#endif\n"
2903 "#ifdef USECOLORMAPPING\n"
2904 "uniform sampler Texture_Pants : register(s4),\n"
2905 "uniform sampler Texture_Shirt : register(s7),\n"
2906 "#endif\n"
2907 "#ifdef USEFOG\n"
2908 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2909 "uniform sampler Texture_FogMask : register(s8),\n"
2910 "#endif\n"
2911 "#ifdef USELIGHTMAP\n"
2912 "uniform sampler Texture_Lightmap : register(s9),\n"
2913 "#endif\n"
2914 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2915 "uniform sampler Texture_Deluxemap : register(s10),\n"
2916 "#endif\n"
2917 "#ifdef USEREFLECTION\n"
2918 "uniform sampler Texture_Reflection : register(s7),\n"
2919 "#endif\n"
2920 "\n"
2921 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2922 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2923 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2924 "#endif\n"
2925 "#ifdef USEDEFERREDLIGHTMAP\n"
2926 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2927 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2928 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2929 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2930 "#endif\n"
2931 "\n"
2932 "#ifdef USECOLORMAPPING\n"
2933 "uniform half3 Color_Pants : register(c7),\n"
2934 "uniform half3 Color_Shirt : register(c8),\n"
2935 "#endif\n"
2936 "#ifdef USEFOG\n"
2937 "uniform float3 FogColor : register(c16),\n"
2938 "uniform float FogRangeRecip : register(c20),\n"
2939 "uniform float FogPlaneViewDist : register(c19),\n"
2940 "uniform float FogHeightFade : register(c17),\n"
2941 "#endif\n"
2942 "\n"
2943 "#ifdef USEOFFSETMAPPING\n"
2944 "uniform float OffsetMapping_Scale : register(c24),\n"
2945 "#endif\n"
2946 "\n"
2947 "#ifdef USEDEFERREDLIGHTMAP\n"
2948 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2949 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2950 "uniform half3 DeferredMod_Specular : register(c13),\n"
2951 "#endif\n"
2952 "uniform half3 Color_Ambient : register(c3),\n"
2953 "uniform half3 Color_Diffuse : register(c4),\n"
2954 "uniform half3 Color_Specular : register(c5),\n"
2955 "uniform half SpecularPower : register(c36),\n"
2956 "#ifdef USEGLOW\n"
2957 "uniform half3 Color_Glow : register(c6),\n"
2958 "#endif\n"
2959 "uniform half Alpha : register(c0),\n"
2960 "#ifdef USEREFLECTION\n"
2961 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2962 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2963 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2964 "uniform half4 ReflectColor : register(c26),\n"
2965 "#endif\n"
2966 "#ifdef USEREFLECTCUBE\n"
2967 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2968 "uniform sampler Texture_ReflectMask : register(s5),\n"
2969 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2970 "#endif\n"
2971 "#ifdef MODE_LIGHTDIRECTION\n"
2972 "uniform half3 LightColor : register(c21),\n"
2973 "#endif\n"
2974 "#ifdef MODE_LIGHTSOURCE\n"
2975 "uniform half3 LightColor : register(c21),\n"
2976 "#endif\n"
2977 "\n"
2978 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2979 "uniform sampler Texture_Attenuation : register(s9),\n"
2980 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2984 "\n"
2985 "#ifdef USESHADOWMAP2D\n"
2986 "# ifdef USESHADOWSAMPLER\n"
2987 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2988 "# else\n"
2989 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2990 "# endif\n"
2991 "#endif\n"
2992 "\n"
2993 "#ifdef USESHADOWMAPVSDCT\n"
2994 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#if defined(USESHADOWMAP2D)\n"
2998 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2999 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3000 "#endif\n"
3001 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3002 "\n"
3003 "out float4 gl_FragColor : COLOR\n"
3004 ")\n"
3005 "{\n"
3006 "       float2 TexCoord = TexCoordBoth.xy;\n"
3007 "#ifdef USEVERTEXTEXTUREBLEND\n"
3008 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3009 "#endif\n"
3010 "#ifdef USEOFFSETMAPPING\n"
3011 "       // apply offsetmapping\n"
3012 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3013 "#define TexCoord TexCoordOffset\n"
3014 "#endif\n"
3015 "\n"
3016 "       // combine the diffuse textures (base, pants, shirt)\n"
3017 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3018 "#ifdef USEALPHAKILL\n"
3019 "       if (color.a < 0.5)\n"
3020 "               discard;\n"
3021 "#endif\n"
3022 "       color.a *= Alpha;\n"
3023 "#ifdef USECOLORMAPPING\n"
3024 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3025 "#endif\n"
3026 "#ifdef USEVERTEXTEXTUREBLEND\n"
3027 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3028 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3029 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3030 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3031 "       color.a = 1.0;\n"
3032 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3033 "#endif\n"
3034 "\n"
3035 "       // get the surface normal\n"
3036 "#ifdef USEVERTEXTEXTUREBLEND\n"
3037 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3038 "#else\n"
3039 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3040 "#endif\n"
3041 "\n"
3042 "       // get the material colors\n"
3043 "       half3 diffusetex = color.rgb;\n"
3044 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3045 "# ifdef USEVERTEXTEXTUREBLEND\n"
3046 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3047 "# else\n"
3048 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3049 "# endif\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef USEREFLECTCUBE\n"
3053 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3054 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3055 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3056 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3057 "#endif\n"
3058 "\n"
3059 "\n"
3060 "\n"
3061 "\n"
3062 "#ifdef MODE_LIGHTSOURCE\n"
3063 "       // light source\n"
3064 "#ifdef USEDIFFUSE\n"
3065 "       half3 lightnormal = half3(normalize(LightVector));\n"
3066 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3067 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3068 "#ifdef USESPECULAR\n"
3069 "#ifdef USEEXACTSPECULARMATH\n"
3070 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3071 "#else\n"
3072 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3073 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3074 "#endif\n"
3075 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3076 "#endif\n"
3077 "#else\n"
3078 "       color.rgb = diffusetex * Color_Ambient;\n"
3079 "#endif\n"
3080 "       color.rgb *= LightColor;\n"
3081 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3082 "#if defined(USESHADOWMAP2D)\n"
3083 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3084 "#ifdef USESHADOWMAPVSDCT\n"
3085 ", Texture_CubeProjection\n"
3086 "#endif\n"
3087 "       ));\n"
3088 "\n"
3089 "#endif\n"
3090 "# ifdef USECUBEFILTER\n"
3091 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3092 "# endif\n"
3093 "\n"
3094 "#ifdef USESHADOWMAP2D\n"
3095 "#ifdef USESHADOWMAPVSDCT\n"
3096 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3097 "#else\n"
3098 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3099 "#endif\n"
3100 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3101 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3102 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3103 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3104 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3105 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3106 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3107 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3108 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3109 "//     color.r = half(shadowmaptc.z);\n"
3110 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3111 "//     color.r = half(shadowmaptc.z);\n"
3112 "//     color.r = 1;\n"
3113 "//     color.rgb = abs(CubeVector);\n"
3114 "#endif\n"
3115 "//     color.rgb = half3(1,1,1);\n"
3116 "#endif // MODE_LIGHTSOURCE\n"
3117 "\n"
3118 "\n"
3119 "\n"
3120 "\n"
3121 "#ifdef MODE_LIGHTDIRECTION\n"
3122 "#define SHADING\n"
3123 "#ifdef USEDIFFUSE\n"
3124 "       half3 lightnormal = half3(normalize(LightVector));\n"
3125 "#endif\n"
3126 "#define lightcolor LightColor\n"
3127 "#endif // MODE_LIGHTDIRECTION\n"
3128 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3129 "#define SHADING\n"
3130 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3131 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3132 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3133 "       // convert modelspace light vector to tangentspace\n"
3134 "       half3 lightnormal;\n"
3135 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3136 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3137 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3138 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3139 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3140 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3141 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3142 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3143 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3144 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3145 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3146 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3147 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3148 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3149 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3150 "#define SHADING\n"
3151 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3152 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3153 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3154 "#endif\n"
3155 "\n"
3156 "\n"
3157 "\n"
3158 "\n"
3159 "#ifdef MODE_LIGHTMAP\n"
3160 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3161 "#endif // MODE_LIGHTMAP\n"
3162 "#ifdef MODE_VERTEXCOLOR\n"
3163 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3164 "#endif // MODE_VERTEXCOLOR\n"
3165 "#ifdef MODE_FLATCOLOR\n"
3166 "       color.rgb = diffusetex * Color_Ambient;\n"
3167 "#endif // MODE_FLATCOLOR\n"
3168 "\n"
3169 "\n"
3170 "\n"
3171 "\n"
3172 "#ifdef SHADING\n"
3173 "# ifdef USEDIFFUSE\n"
3174 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3175 "#  ifdef USESPECULAR\n"
3176 "#   ifdef USEEXACTSPECULARMATH\n"
3177 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3178 "#   else\n"
3179 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3180 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3181 "#   endif\n"
3182 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3183 "#  else\n"
3184 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3185 "#  endif\n"
3186 "# else\n"
3187 "       color.rgb = diffusetex * Color_Ambient;\n"
3188 "# endif\n"
3189 "#endif\n"
3190 "\n"
3191 "#ifdef USESHADOWMAPORTHO\n"
3192 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3193 "#endif\n"
3194 "\n"
3195 "#ifdef USEDEFERREDLIGHTMAP\n"
3196 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3197 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3198 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3199 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3200 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3201 "#endif\n"
3202 "\n"
3203 "#ifdef USEGLOW\n"
3204 "#ifdef USEVERTEXTEXTUREBLEND\n"
3205 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3206 "#else\n"
3207 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3208 "#endif\n"
3209 "#endif\n"
3210 "\n"
3211 "#ifdef USEFOG\n"
3212 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3213 "#endif\n"
3214 "\n"
3215 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3216 "#ifdef USEREFLECTION\n"
3217 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3218 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3219 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3220 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3221 "       // FIXME temporary hack to detect the case that the reflection\n"
3222 "       // gets blackened at edges due to leaving the area that contains actual\n"
3223 "       // content.\n"
3224 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3225 "       // 'appening.\n"
3226 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3227 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3228 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3229 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3230 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3231 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3232 "#endif\n"
3233 "\n"
3234 "       gl_FragColor = float4(color);\n"
3235 "}\n"
3236 "#endif // FRAGMENT_SHADER\n"
3237 "\n"
3238 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3239 "#endif // !MODE_DEFERREDGEOMETRY\n"
3240 "#endif // !MODE_WATER\n"
3241 "#endif // !MODE_REFRACTION\n"
3242 "#endif // !MODE_BLOOMBLUR\n"
3243 "#endif // !MODE_GENERIC\n"
3244 "#endif // !MODE_POSTPROCESS\n"
3245 "#endif // !MODE_SHOWDEPTH\n"
3246 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3247 ;
3248
3249 char *glslshaderstring = NULL;
3250 char *cgshaderstring = NULL;
3251 char *hlslshaderstring = NULL;
3252
3253 //=======================================================================================================================================================
3254
3255 typedef struct shaderpermutationinfo_s
3256 {
3257         const char *pretext;
3258         const char *name;
3259 }
3260 shaderpermutationinfo_t;
3261
3262 typedef struct shadermodeinfo_s
3263 {
3264         const char *vertexfilename;
3265         const char *geometryfilename;
3266         const char *fragmentfilename;
3267         const char *pretext;
3268         const char *name;
3269 }
3270 shadermodeinfo_t;
3271
3272 typedef enum shaderpermutation_e
3273 {
3274         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3275         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3276         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3277         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3278         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3279         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3280         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3281         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3282         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3283         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3284         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3285         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3286         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3287         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3288         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3289         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3290         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3291         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3292         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3293         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3294         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3295         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3296         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3297         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3298         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3299         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3300         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3301         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3302         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3303 }
3304 shaderpermutation_t;
3305
3306 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3307 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3308 {
3309         {"#define USEDIFFUSE\n", " diffuse"},
3310         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3311         {"#define USEVIEWTINT\n", " viewtint"},
3312         {"#define USECOLORMAPPING\n", " colormapping"},
3313         {"#define USESATURATION\n", " saturation"},
3314         {"#define USEFOGINSIDE\n", " foginside"},
3315         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3316         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3317         {"#define USEGAMMARAMPS\n", " gammaramps"},
3318         {"#define USECUBEFILTER\n", " cubefilter"},
3319         {"#define USEGLOW\n", " glow"},
3320         {"#define USEBLOOM\n", " bloom"},
3321         {"#define USESPECULAR\n", " specular"},
3322         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3323         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3324         {"#define USEREFLECTION\n", " reflection"},
3325         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3326         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3327         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3328         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3329         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3330         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3331         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3332         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3333         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3334         {"#define USEALPHAKILL\n", " alphakill"},
3335         {"#define USEREFLECTCUBE\n", " reflectcube"},
3336 };
3337
3338 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3339 typedef enum shadermode_e
3340 {
3341         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3342         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3343         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3344         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3345         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3346         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3347         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3348         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3349         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3350         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3351         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3352         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3353         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3354         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3355         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3356         SHADERMODE_COUNT
3357 }
3358 shadermode_t;
3359
3360 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3361 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3362 {
3363         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3364         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3365         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3366         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3367         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3368         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3369         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3370         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3371         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3372         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3373         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3374         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3375         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3376         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3377         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3378 };
3379
3380 #ifdef SUPPORTCG
3381 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3382 {
3383         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3384         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3385         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3386         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3387         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3388         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3389         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3390         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3391         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3392         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3393         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3394         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3395         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3396         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3397         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3398 };
3399 #endif
3400
3401 #ifdef SUPPORTD3D
3402 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3403 {
3404         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3405         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3406         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3407         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3408         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3409         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3410         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3411         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3412         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3413         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3414         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3415         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3416         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3417         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3419 };
3420 #endif
3421
3422 struct r_glsl_permutation_s;
3423 typedef struct r_glsl_permutation_s
3424 {
3425         /// hash lookup data
3426         struct r_glsl_permutation_s *hashnext;
3427         unsigned int mode;
3428         unsigned int permutation;
3429
3430         /// indicates if we have tried compiling this permutation already
3431         qboolean compiled;
3432         /// 0 if compilation failed
3433         int program;
3434         /// locations of detected uniforms in program object, or -1 if not found
3435         int loc_Texture_First;
3436         int loc_Texture_Second;
3437         int loc_Texture_GammaRamps;
3438         int loc_Texture_Normal;
3439         int loc_Texture_Color;
3440         int loc_Texture_Gloss;
3441         int loc_Texture_Glow;
3442         int loc_Texture_SecondaryNormal;
3443         int loc_Texture_SecondaryColor;
3444         int loc_Texture_SecondaryGloss;
3445         int loc_Texture_SecondaryGlow;
3446         int loc_Texture_Pants;
3447         int loc_Texture_Shirt;
3448         int loc_Texture_FogHeightTexture;
3449         int loc_Texture_FogMask;
3450         int loc_Texture_Lightmap;
3451         int loc_Texture_Deluxemap;
3452         int loc_Texture_Attenuation;
3453         int loc_Texture_Cube;
3454         int loc_Texture_Refraction;
3455         int loc_Texture_Reflection;
3456         int loc_Texture_ShadowMap2D;
3457         int loc_Texture_CubeProjection;
3458         int loc_Texture_ScreenDepth;
3459         int loc_Texture_ScreenNormalMap;
3460         int loc_Texture_ScreenDiffuse;
3461         int loc_Texture_ScreenSpecular;
3462         int loc_Texture_ReflectMask;
3463         int loc_Texture_ReflectCube;
3464         int loc_Alpha;
3465         int loc_BloomBlur_Parameters;
3466         int loc_ClientTime;
3467         int loc_Color_Ambient;
3468         int loc_Color_Diffuse;
3469         int loc_Color_Specular;
3470         int loc_Color_Glow;
3471         int loc_Color_Pants;
3472         int loc_Color_Shirt;
3473         int loc_DeferredColor_Ambient;
3474         int loc_DeferredColor_Diffuse;
3475         int loc_DeferredColor_Specular;
3476         int loc_DeferredMod_Diffuse;
3477         int loc_DeferredMod_Specular;
3478         int loc_DistortScaleRefractReflect;
3479         int loc_EyePosition;
3480         int loc_FogColor;
3481         int loc_FogHeightFade;
3482         int loc_FogPlane;
3483         int loc_FogPlaneViewDist;
3484         int loc_FogRangeRecip;
3485         int loc_LightColor;
3486         int loc_LightDir;
3487         int loc_LightPosition;
3488         int loc_OffsetMapping_Scale;
3489         int loc_PixelSize;
3490         int loc_ReflectColor;
3491         int loc_ReflectFactor;
3492         int loc_ReflectOffset;
3493         int loc_RefractColor;
3494         int loc_Saturation;
3495         int loc_ScreenCenterRefractReflect;
3496         int loc_ScreenScaleRefractReflect;
3497         int loc_ScreenToDepth;
3498         int loc_ShadowMap_Parameters;
3499         int loc_ShadowMap_TextureScale;
3500         int loc_SpecularPower;
3501         int loc_UserVec1;
3502         int loc_UserVec2;
3503         int loc_UserVec3;
3504         int loc_UserVec4;
3505         int loc_ViewTintColor;
3506         int loc_ViewToLight;
3507         int loc_ModelToLight;
3508         int loc_TexMatrix;
3509         int loc_BackgroundTexMatrix;
3510         int loc_ModelViewProjectionMatrix;
3511         int loc_ModelViewMatrix;
3512         int loc_PixelToScreenTexCoord;
3513         int loc_ModelToReflectCube;
3514         int loc_ShadowMapMatrix;
3515         int loc_BloomColorSubtract;
3516 }
3517 r_glsl_permutation_t;
3518
3519 #define SHADERPERMUTATION_HASHSIZE 256
3520
3521 /// information about each possible shader permutation
3522 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3523 /// currently selected permutation
3524 r_glsl_permutation_t *r_glsl_permutation;
3525 /// storage for permutations linked in the hash table
3526 memexpandablearray_t r_glsl_permutationarray;
3527
3528 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3529 {
3530         //unsigned int hashdepth = 0;
3531         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3532         r_glsl_permutation_t *p;
3533         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3534         {
3535                 if (p->mode == mode && p->permutation == permutation)
3536                 {
3537                         //if (hashdepth > 10)
3538                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3539                         return p;
3540                 }
3541                 //hashdepth++;
3542         }
3543         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3544         p->mode = mode;
3545         p->permutation = permutation;
3546         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3547         r_glsl_permutationhash[mode][hashindex] = p;
3548         //if (hashdepth > 10)
3549         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3550         return p;
3551 }
3552
3553 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3554 {
3555         char *shaderstring;
3556         if (!filename || !filename[0])
3557                 return NULL;
3558         if (!strcmp(filename, "glsl/default.glsl"))
3559         {
3560                 if (!glslshaderstring)
3561                 {
3562                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3563                         if (glslshaderstring)
3564                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3565                         else
3566                                 glslshaderstring = (char *)builtinshaderstring;
3567                 }
3568                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3569                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3570                 return shaderstring;
3571         }
3572         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3573         if (shaderstring)
3574         {
3575                 if (printfromdisknotice)
3576                         Con_DPrintf("from disk %s... ", filename);
3577                 return shaderstring;
3578         }
3579         return shaderstring;
3580 }
3581
3582 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3583 {
3584         int i;
3585         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3586         int vertstrings_count = 0;
3587         int geomstrings_count = 0;
3588         int fragstrings_count = 0;
3589         char *vertexstring, *geometrystring, *fragmentstring;
3590         const char *vertstrings_list[32+3];
3591         const char *geomstrings_list[32+3];
3592         const char *fragstrings_list[32+3];
3593         char permutationname[256];
3594
3595         if (p->compiled)
3596                 return;
3597         p->compiled = true;
3598         p->program = 0;
3599
3600         permutationname[0] = 0;
3601         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3602         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3603         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3604
3605         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3606
3607         // the first pretext is which type of shader to compile as
3608         // (later these will all be bound together as a program object)
3609         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3610         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3611         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3612
3613         // the second pretext is the mode (for example a light source)
3614         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3615         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3616         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3617         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3618
3619         // now add all the permutation pretexts
3620         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3621         {
3622                 if (permutation & (1<<i))
3623                 {
3624                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3625                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3626                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3627                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3628                 }
3629                 else
3630                 {
3631                         // keep line numbers correct
3632                         vertstrings_list[vertstrings_count++] = "\n";
3633                         geomstrings_list[geomstrings_count++] = "\n";
3634                         fragstrings_list[fragstrings_count++] = "\n";
3635                 }
3636         }
3637
3638         // now append the shader text itself
3639         vertstrings_list[vertstrings_count++] = vertexstring;
3640         geomstrings_list[geomstrings_count++] = geometrystring;
3641         fragstrings_list[fragstrings_count++] = fragmentstring;
3642
3643         // if any sources were NULL, clear the respective list
3644         if (!vertexstring)
3645                 vertstrings_count = 0;
3646         if (!geometrystring)
3647                 geomstrings_count = 0;
3648         if (!fragmentstring)
3649                 fragstrings_count = 0;
3650
3651         // compile the shader program
3652         if (vertstrings_count + geomstrings_count + fragstrings_count)
3653                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3654         if (p->program)
3655         {
3656                 CHECKGLERROR
3657                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3658                 // look up all the uniform variable names we care about, so we don't
3659                 // have to look them up every time we set them
3660
3661                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3662                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3663                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3664                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3665                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3666                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3667                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3668                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3669                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3670                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3671                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3672                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3673                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3674                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3675                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3676                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3677                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3678                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3679                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3680                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3681                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3682                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3683                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3684                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3685                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3686                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3687                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3688                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3689                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3690                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3691                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3692                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3693                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3694                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3695                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3696                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3697                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3698                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3699                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3700                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3701                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3702                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3703                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3704                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3705                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3706                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3707                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3708                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3709                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3710                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3711                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3712                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3713                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3714                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3715                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3716                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3717                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3718                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3719                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3720                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3721                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3722                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3723                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3724                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3725                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3726                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3727                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3728                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3729                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3730                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3731                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3732                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3733                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3734                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3735                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3736                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3737                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3738                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3739                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3740                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3741                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3742                 // initialize the samplers to refer to the texture units we use
3743                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3744                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3745                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3746                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3747                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3748                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3749                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3750                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3751                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3752                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3753                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3754                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3755                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3756                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3757                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3758                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3759                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3760                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3761                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3762                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3763                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3764                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3765                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3766                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3767                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3768                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3769                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3770                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3771                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3772                 CHECKGLERROR
3773                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3774         }
3775         else
3776                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3777
3778         // free the strings
3779         if (vertexstring)
3780                 Mem_Free(vertexstring);
3781         if (geometrystring)
3782                 Mem_Free(geometrystring);
3783         if (fragmentstring)
3784                 Mem_Free(fragmentstring);
3785 }
3786
3787 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3788 {
3789         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3790         if (r_glsl_permutation != perm)
3791         {
3792                 r_glsl_permutation = perm;
3793                 if (!r_glsl_permutation->program)
3794                 {
3795                         if (!r_glsl_permutation->compiled)
3796                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3797                         if (!r_glsl_permutation->program)
3798                         {
3799                                 // remove features until we find a valid permutation
3800                                 int i;
3801                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3802                                 {
3803                                         // reduce i more quickly whenever it would not remove any bits
3804                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3805                                         if (!(permutation & j))
3806                                                 continue;
3807                                         permutation -= j;
3808                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3809                                         if (!r_glsl_permutation->compiled)
3810                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3811                                         if (r_glsl_permutation->program)
3812                                                 break;
3813                                 }
3814                                 if (i >= SHADERPERMUTATION_COUNT)
3815                                 {
3816                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3817                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3818                                         qglUseProgramObjectARB(0);CHECKGLERROR
3819                                         return; // no bit left to clear, entire mode is broken
3820                                 }
3821                         }
3822                 }
3823                 CHECKGLERROR
3824                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3825         }
3826         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3827         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3828         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3829 }
3830
3831 #ifdef SUPPORTCG
3832 #include <Cg/cgGL.h>
3833 struct r_cg_permutation_s;
3834 typedef struct r_cg_permutation_s
3835 {
3836         /// hash lookup data
3837         struct r_cg_permutation_s *hashnext;
3838         unsigned int mode;
3839         unsigned int permutation;
3840
3841         /// indicates if we have tried compiling this permutation already
3842         qboolean compiled;
3843         /// 0 if compilation failed
3844         CGprogram vprogram;
3845         CGprogram fprogram;
3846         /// locations of detected parameters in programs, or NULL if not found
3847         CGparameter vp_EyePosition;
3848         CGparameter vp_FogPlane;
3849         CGparameter vp_LightDir;
3850         CGparameter vp_LightPosition;
3851         CGparameter vp_ModelToLight;
3852         CGparameter vp_TexMatrix;
3853         CGparameter vp_BackgroundTexMatrix;
3854         CGparameter vp_ModelViewProjectionMatrix;
3855         CGparameter vp_ModelViewMatrix;
3856         CGparameter vp_ShadowMapMatrix;
3857
3858         CGparameter fp_Texture_First;
3859         CGparameter fp_Texture_Second;
3860         CGparameter fp_Texture_GammaRamps;
3861         CGparameter fp_Texture_Normal;
3862         CGparameter fp_Texture_Color;
3863         CGparameter fp_Texture_Gloss;
3864         CGparameter fp_Texture_Glow;
3865         CGparameter fp_Texture_SecondaryNormal;
3866         CGparameter fp_Texture_SecondaryColor;
3867         CGparameter fp_Texture_SecondaryGloss;
3868         CGparameter fp_Texture_SecondaryGlow;
3869         CGparameter fp_Texture_Pants;
3870         CGparameter fp_Texture_Shirt;
3871         CGparameter fp_Texture_FogHeightTexture;
3872         CGparameter fp_Texture_FogMask;
3873         CGparameter fp_Texture_Lightmap;
3874         CGparameter fp_Texture_Deluxemap;
3875         CGparameter fp_Texture_Attenuation;
3876         CGparameter fp_Texture_Cube;
3877         CGparameter fp_Texture_Refraction;
3878         CGparameter fp_Texture_Reflection;
3879         CGparameter fp_Texture_ShadowMap2D;
3880         CGparameter fp_Texture_CubeProjection;
3881         CGparameter fp_Texture_ScreenDepth;
3882         CGparameter fp_Texture_ScreenNormalMap;
3883         CGparameter fp_Texture_ScreenDiffuse;
3884         CGparameter fp_Texture_ScreenSpecular;
3885         CGparameter fp_Texture_ReflectMask;
3886         CGparameter fp_Texture_ReflectCube;
3887         CGparameter fp_Alpha;
3888         CGparameter fp_BloomBlur_Parameters;
3889         CGparameter fp_ClientTime;
3890         CGparameter fp_Color_Ambient;
3891         CGparameter fp_Color_Diffuse;
3892         CGparameter fp_Color_Specular;
3893         CGparameter fp_Color_Glow;
3894         CGparameter fp_Color_Pants;
3895         CGparameter fp_Color_Shirt;
3896         CGparameter fp_DeferredColor_Ambient;
3897         CGparameter fp_DeferredColor_Diffuse;
3898         CGparameter fp_DeferredColor_Specular;
3899         CGparameter fp_DeferredMod_Diffuse;
3900         CGparameter fp_DeferredMod_Specular;
3901         CGparameter fp_DistortScaleRefractReflect;
3902         CGparameter fp_EyePosition;
3903         CGparameter fp_FogColor;
3904         CGparameter fp_FogHeightFade;
3905         CGparameter fp_FogPlane;
3906         CGparameter fp_FogPlaneViewDist;
3907         CGparameter fp_FogRangeRecip;
3908         CGparameter fp_LightColor;
3909         CGparameter fp_LightDir;
3910         CGparameter fp_LightPosition;
3911         CGparameter fp_OffsetMapping_Scale;
3912         CGparameter fp_PixelSize;
3913         CGparameter fp_ReflectColor;
3914         CGparameter fp_ReflectFactor;
3915         CGparameter fp_ReflectOffset;
3916         CGparameter fp_RefractColor;
3917         CGparameter fp_Saturation;
3918         CGparameter fp_ScreenCenterRefractReflect;
3919         CGparameter fp_ScreenScaleRefractReflect;
3920         CGparameter fp_ScreenToDepth;
3921         CGparameter fp_ShadowMap_Parameters;
3922         CGparameter fp_ShadowMap_TextureScale;
3923         CGparameter fp_SpecularPower;
3924         CGparameter fp_UserVec1;
3925         CGparameter fp_UserVec2;
3926         CGparameter fp_UserVec3;
3927         CGparameter fp_UserVec4;
3928         CGparameter fp_ViewTintColor;
3929         CGparameter fp_ViewToLight;
3930         CGparameter fp_PixelToScreenTexCoord;
3931         CGparameter fp_ModelToReflectCube;
3932         CGparameter fp_BloomColorSubtract;
3933 }
3934 r_cg_permutation_t;
3935
3936 /// information about each possible shader permutation
3937 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3938 /// currently selected permutation
3939 r_cg_permutation_t *r_cg_permutation;
3940 /// storage for permutations linked in the hash table
3941 memexpandablearray_t r_cg_permutationarray;
3942
3943 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3944
3945 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3946 {
3947         //unsigned int hashdepth = 0;
3948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3949         r_cg_permutation_t *p;
3950         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3951         {
3952                 if (p->mode == mode && p->permutation == permutation)
3953                 {
3954                         //if (hashdepth > 10)
3955                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3956                         return p;
3957                 }
3958                 //hashdepth++;
3959         }
3960         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3961         p->mode = mode;
3962         p->permutation = permutation;
3963         p->hashnext = r_cg_permutationhash[mode][hashindex];
3964         r_cg_permutationhash[mode][hashindex] = p;
3965         //if (hashdepth > 10)
3966         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3967         return p;
3968 }
3969
3970 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3971 {
3972         char *shaderstring;
3973         if (!filename || !filename[0])
3974                 return NULL;
3975         if (!strcmp(filename, "cg/default.cg"))
3976         {
3977                 if (!cgshaderstring)
3978                 {
3979                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3980                         if (cgshaderstring)
3981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3982                         else
3983                                 cgshaderstring = (char *)builtincgshaderstring;
3984                 }
3985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3986                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3987                 return shaderstring;
3988         }
3989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3990         if (shaderstring)
3991         {
3992                 if (printfromdisknotice)
3993                         Con_DPrintf("from disk %s... ", filename);
3994                 return shaderstring;
3995         }
3996         return shaderstring;
3997 }
3998
3999 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4000 {
4001         // TODO: load or create .fp and .vp shader files
4002 }
4003
4004 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4005 {
4006         int i;
4007         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4008         int vertstrings_count = 0, vertstring_length = 0;
4009         int geomstrings_count = 0, geomstring_length = 0;
4010         int fragstrings_count = 0, fragstring_length = 0;
4011         char *t;
4012         char *vertexstring, *geometrystring, *fragmentstring;
4013         char *vertstring, *geomstring, *fragstring;
4014         const char *vertstrings_list[32+3];
4015         const char *geomstrings_list[32+3];
4016         const char *fragstrings_list[32+3];
4017         char permutationname[256];
4018         char cachename[256];
4019         CGprofile vertexProfile;
4020         CGprofile fragmentProfile;
4021
4022         if (p->compiled)
4023                 return;
4024         p->compiled = true;
4025         p->vprogram = NULL;
4026         p->fprogram = NULL;
4027
4028         permutationname[0] = 0;
4029         cachename[0] = 0;
4030         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4031         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4032         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4033
4034         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4035         strlcat(cachename, "cg/", sizeof(cachename));
4036
4037         // the first pretext is which type of shader to compile as
4038         // (later these will all be bound together as a program object)
4039         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4040         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4041         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4042
4043         // the second pretext is the mode (for example a light source)
4044         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4045         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4046         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4047         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4048         strlcat(cachename, modeinfo->name, sizeof(cachename));
4049
4050         // now add all the permutation pretexts
4051         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4052         {
4053                 if (permutation & (1<<i))
4054                 {
4055                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4056                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4057                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4058                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4059                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4060                 }
4061                 else
4062                 {
4063                         // keep line numbers correct
4064                         vertstrings_list[vertstrings_count++] = "\n";
4065                         geomstrings_list[geomstrings_count++] = "\n";
4066                         fragstrings_list[fragstrings_count++] = "\n";
4067                 }
4068         }
4069
4070         // replace spaces in the cachename with _ characters
4071         for (i = 0;cachename[i];i++)
4072                 if (cachename[i] == ' ')
4073                         cachename[i] = '_';
4074
4075         // now append the shader text itself
4076         vertstrings_list[vertstrings_count++] = vertexstring;
4077         geomstrings_list[geomstrings_count++] = geometrystring;
4078         fragstrings_list[fragstrings_count++] = fragmentstring;
4079
4080         // if any sources were NULL, clear the respective list
4081         if (!vertexstring)
4082                 vertstrings_count = 0;
4083         if (!geometrystring)
4084                 geomstrings_count = 0;
4085         if (!fragmentstring)
4086                 fragstrings_count = 0;
4087
4088         vertstring_length = 0;
4089         for (i = 0;i < vertstrings_count;i++)
4090                 vertstring_length += strlen(vertstrings_list[i]);
4091         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4092         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4093                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4094
4095         geomstring_length = 0;
4096         for (i = 0;i < geomstrings_count;i++)
4097                 geomstring_length += strlen(geomstrings_list[i]);
4098         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4099         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4100                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4101
4102         fragstring_length = 0;
4103         for (i = 0;i < fragstrings_count;i++)
4104                 fragstring_length += strlen(fragstrings_list[i]);
4105         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4106         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4107                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4108
4109         CHECKGLERROR
4110         CHECKCGERROR
4111         //vertexProfile = CG_PROFILE_ARBVP1;
4112         //fragmentProfile = CG_PROFILE_ARBFP1;
4113         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4114         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4115         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4116         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4117         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4118         CHECKGLERROR
4119
4120         // try to load the cached shader, or generate one
4121         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4122
4123         // if caching failed, do a dynamic compile for now
4124         CHECKCGERROR
4125         if (vertstring[0] && !p->vprogram)
4126                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4127         CHECKCGERROR
4128         if (fragstring[0] && !p->fprogram)
4129                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4130         CHECKCGERROR
4131
4132         // look up all the uniform variable names we care about, so we don't
4133         // have to look them up every time we set them
4134         if (p->vprogram)
4135         {
4136                 CHECKCGERROR
4137                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4138                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4139                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4140                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4141                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4142                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4143                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4144                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4145                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4146                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4147                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4148                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4149                 CHECKCGERROR
4150         }
4151         if (p->fprogram)
4152         {
4153                 CHECKCGERROR
4154                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4155                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4156                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4157                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4158                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4159                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4160                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4161                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4162                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4163                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4164                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4165                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4166                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4167                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4168                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4169                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4170                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4171                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4172                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4173                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4174                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4175                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4176                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4177                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4178                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4179                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4180                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4181                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4182                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4183                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4184                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4185                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4186                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4187                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4188                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4189                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4190                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4191                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4192                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4193                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4194                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4195                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4196                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4197                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4198                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4199                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4200                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4201                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4202                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4203                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4204                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4205                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4206                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4207                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4208                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4209                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4210                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4211                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4212                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4213                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4214                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4215                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4216                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4217                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4218                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4219                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4220                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4221                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4222                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4223                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4224                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4225                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4226                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4227                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4228                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4229                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4230                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4231                 CHECKCGERROR
4232         }
4233
4234         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4235                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4236         else
4237                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4238
4239         // free the strings
4240         if (vertstring)
4241                 Mem_Free(vertstring);
4242         if (geomstring)
4243                 Mem_Free(geomstring);
4244         if (fragstring)
4245                 Mem_Free(fragstring);
4246         if (vertexstring)
4247                 Mem_Free(vertexstring);
4248         if (geometrystring)
4249                 Mem_Free(geometrystring);
4250         if (fragmentstring)
4251                 Mem_Free(fragmentstring);
4252 }
4253
4254 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4255 {
4256         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4257         CHECKGLERROR
4258         CHECKCGERROR
4259         if (r_cg_permutation != perm)
4260         {
4261                 r_cg_permutation = perm;
4262                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4263                 {
4264                         if (!r_cg_permutation->compiled)
4265                                 R_CG_CompilePermutation(perm, mode, permutation);
4266                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4267                         {
4268                                 // remove features until we find a valid permutation
4269                                 int i;
4270                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271                                 {
4272                                         // reduce i more quickly whenever it would not remove any bits
4273                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4274                                         if (!(permutation & j))
4275                                                 continue;
4276                                         permutation -= j;
4277                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4278                                         if (!r_cg_permutation->compiled)
4279                                                 R_CG_CompilePermutation(perm, mode, permutation);
4280                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4281                                                 break;
4282                                 }
4283                                 if (i >= SHADERPERMUTATION_COUNT)
4284                                 {
4285                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4286                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4287                                         return; // no bit left to clear, entire mode is broken
4288                                 }
4289                         }
4290                 }
4291                 CHECKGLERROR
4292                 CHECKCGERROR
4293                 if (r_cg_permutation->vprogram)
4294                 {
4295                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4296                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4297                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4298                 }
4299                 else
4300                 {
4301                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4302                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4303                 }
4304                 if (r_cg_permutation->fprogram)
4305                 {
4306                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4307                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4308                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4309                 }
4310                 else
4311                 {
4312                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4313                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4314                 }
4315         }
4316         CHECKCGERROR
4317         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4318         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4319         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4320 }
4321
4322 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4323 {
4324         cgGLSetTextureParameter(param, R_GetTexture(tex));
4325         cgGLEnableTextureParameter(param);
4326 }
4327 #endif
4328
4329 #ifdef SUPPORTD3D
4330
4331 #ifdef SUPPORTD3D
4332 #include <d3d9.h>
4333 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4334 extern D3DCAPS9 vid_d3d9caps;
4335 #endif
4336
4337 struct r_hlsl_permutation_s;
4338 typedef struct r_hlsl_permutation_s
4339 {
4340         /// hash lookup data
4341         struct r_hlsl_permutation_s *hashnext;
4342         unsigned int mode;
4343         unsigned int permutation;
4344
4345         /// indicates if we have tried compiling this permutation already
4346         qboolean compiled;
4347         /// NULL if compilation failed
4348         IDirect3DVertexShader9 *vertexshader;
4349         IDirect3DPixelShader9 *pixelshader;
4350 }
4351 r_hlsl_permutation_t;
4352
4353 typedef enum D3DVSREGISTER_e
4354 {
4355         D3DVSREGISTER_TexMatrix = 0, // float4x4
4356         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4357         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4358         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4359         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4360         D3DVSREGISTER_ModelToLight = 20, // float4x4
4361         D3DVSREGISTER_EyePosition = 24,
4362         D3DVSREGISTER_FogPlane = 25,
4363         D3DVSREGISTER_LightDir = 26,
4364         D3DVSREGISTER_LightPosition = 27,
4365 }
4366 D3DVSREGISTER_t;
4367
4368 typedef enum D3DPSREGISTER_e
4369 {
4370         D3DPSREGISTER_Alpha = 0,
4371         D3DPSREGISTER_BloomBlur_Parameters = 1,
4372         D3DPSREGISTER_ClientTime = 2,
4373         D3DPSREGISTER_Color_Ambient = 3,
4374         D3DPSREGISTER_Color_Diffuse = 4,
4375         D3DPSREGISTER_Color_Specular = 5,
4376         D3DPSREGISTER_Color_Glow = 6,
4377         D3DPSREGISTER_Color_Pants = 7,
4378         D3DPSREGISTER_Color_Shirt = 8,
4379         D3DPSREGISTER_DeferredColor_Ambient = 9,
4380         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4381         D3DPSREGISTER_DeferredColor_Specular = 11,
4382         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4383         D3DPSREGISTER_DeferredMod_Specular = 13,
4384         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4385         D3DPSREGISTER_EyePosition = 15, // unused
4386         D3DPSREGISTER_FogColor = 16,
4387         D3DPSREGISTER_FogHeightFade = 17,
4388         D3DPSREGISTER_FogPlane = 18,
4389         D3DPSREGISTER_FogPlaneViewDist = 19,
4390         D3DPSREGISTER_FogRangeRecip = 20,
4391         D3DPSREGISTER_LightColor = 21,
4392         D3DPSREGISTER_LightDir = 22, // unused
4393         D3DPSREGISTER_LightPosition = 23,
4394         D3DPSREGISTER_OffsetMapping_Scale = 24,
4395         D3DPSREGISTER_PixelSize = 25,
4396         D3DPSREGISTER_ReflectColor = 26,
4397         D3DPSREGISTER_ReflectFactor = 27,
4398         D3DPSREGISTER_ReflectOffset = 28,
4399         D3DPSREGISTER_RefractColor = 29,
4400         D3DPSREGISTER_Saturation = 30,
4401         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4402         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4403         D3DPSREGISTER_ScreenToDepth = 33,
4404         D3DPSREGISTER_ShadowMap_Parameters = 34,
4405         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4406         D3DPSREGISTER_SpecularPower = 36,
4407         D3DPSREGISTER_UserVec1 = 37,
4408         D3DPSREGISTER_UserVec2 = 38,
4409         D3DPSREGISTER_UserVec3 = 39,
4410         D3DPSREGISTER_UserVec4 = 40,
4411         D3DPSREGISTER_ViewTintColor = 41,
4412         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4413         D3DPSREGISTER_BloomColorSubtract = 43,
4414         D3DPSREGISTER_ViewToLight = 44, // float4x4
4415         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4416         // next at 52
4417 }
4418 D3DPSREGISTER_t;
4419
4420 /// information about each possible shader permutation
4421 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4422 /// currently selected permutation
4423 r_hlsl_permutation_t *r_hlsl_permutation;
4424 /// storage for permutations linked in the hash table
4425 memexpandablearray_t r_hlsl_permutationarray;
4426
4427 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4428 {
4429         //unsigned int hashdepth = 0;
4430         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4431         r_hlsl_permutation_t *p;
4432         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4433         {
4434                 if (p->mode == mode && p->permutation == permutation)
4435                 {
4436                         //if (hashdepth > 10)
4437                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4438                         return p;
4439                 }
4440                 //hashdepth++;
4441         }
4442         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4443         p->mode = mode;
4444         p->permutation = permutation;
4445         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4446         r_hlsl_permutationhash[mode][hashindex] = p;
4447         //if (hashdepth > 10)
4448         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4449         return p;
4450 }
4451
4452 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4453 {
4454         char *shaderstring;
4455         if (!filename || !filename[0])
4456                 return NULL;
4457         if (!strcmp(filename, "hlsl/default.hlsl"))
4458         {
4459                 if (!hlslshaderstring)
4460                 {
4461                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4462                         if (hlslshaderstring)
4463                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4464                         else
4465                                 hlslshaderstring = (char *)builtincgshaderstring;
4466                 }
4467                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4468                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4469                 return shaderstring;
4470         }
4471         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4472         if (shaderstring)
4473         {
4474                 if (printfromdisknotice)
4475                         Con_DPrintf("from disk %s... ", filename);
4476                 return shaderstring;
4477         }
4478         return shaderstring;
4479 }
4480
4481 #include <d3dx9.h>
4482 //#include <d3dx9shader.h>
4483 //#include <d3dx9mesh.h>
4484
4485 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4486 {
4487         DWORD *vsbin = NULL;
4488         DWORD *psbin = NULL;
4489         fs_offset_t vsbinsize;
4490         fs_offset_t psbinsize;
4491 //      IDirect3DVertexShader9 *vs = NULL;
4492 //      IDirect3DPixelShader9 *ps = NULL;
4493         ID3DXBuffer *vslog = NULL;
4494         ID3DXBuffer *vsbuffer = NULL;
4495         ID3DXConstantTable *vsconstanttable = NULL;
4496         ID3DXBuffer *pslog = NULL;
4497         ID3DXBuffer *psbuffer = NULL;
4498         ID3DXConstantTable *psconstanttable = NULL;
4499         int vsresult = 0;
4500         int psresult = 0;
4501         char temp[MAX_INPUTLINE];
4502         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4503         qboolean debugshader = gl_paranoid.integer != 0;
4504         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4505         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4506         if (!debugshader)
4507         {
4508                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4509                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4510         }
4511         if ((!vsbin && vertstring) || (!psbin && fragstring))
4512         {
4513                 const char* dllnames_d3dx9 [] =
4514                 {
4515                         "d3dx9_43.dll",
4516                         "d3dx9_42.dll",
4517                         "d3dx9_41.dll",
4518                         "d3dx9_40.dll",
4519                         "d3dx9_39.dll",
4520                         "d3dx9_38.dll",
4521                         "d3dx9_37.dll",
4522                         "d3dx9_36.dll",
4523                         "d3dx9_35.dll",
4524                         "d3dx9_34.dll",
4525                         "d3dx9_33.dll",
4526                         "d3dx9_32.dll",
4527                         "d3dx9_31.dll",
4528                         "d3dx9_30.dll",
4529                         "d3dx9_29.dll",
4530                         "d3dx9_28.dll",
4531                         "d3dx9_27.dll",
4532                         "d3dx9_26.dll",
4533                         "d3dx9_25.dll",
4534                         "d3dx9_24.dll",
4535                         NULL
4536                 };
4537                 dllhandle_t d3dx9_dll = NULL;
4538                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4539                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4540                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4541                 dllfunction_t d3dx9_dllfuncs[] =
4542                 {
4543                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4544                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4545                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4546                         {NULL, NULL}
4547                 };
4548                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4549                 {
4550                         DWORD shaderflags = 0;
4551                         if (debugshader)
4552                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4553                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4554                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4555                         if (vertstring && vertstring[0])
4556                         {
4557                                 if (debugshader)
4558                                 {
4559 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4560 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4561                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4562                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4563                                 }
4564                                 else
4565                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4566                                 if (vsbuffer)
4567                                 {
4568                                         vsbinsize = vsbuffer->GetBufferSize();
4569                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4570                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4571                                         vsbuffer->Release();
4572                                 }
4573                                 if (vslog)
4574                                 {
4575                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4576                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4577                                         vslog->Release();
4578                                 }
4579                         }
4580                         if (fragstring && fragstring[0])
4581                         {
4582                                 if (debugshader)
4583                                 {
4584 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4585 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4586                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4587                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4588                                 }
4589                                 else
4590                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4591                                 if (psbuffer)
4592                                 {
4593                                         psbinsize = psbuffer->GetBufferSize();
4594                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4595                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4596                                         psbuffer->Release();
4597                                 }
4598                                 if (pslog)
4599                                 {
4600                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4601                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4602                                         pslog->Release();
4603                                 }
4604                         }
4605                         Sys_UnloadLibrary(&d3dx9_dll);
4606                 }
4607                 else
4608                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4609         }
4610         if (vsbin && psbin)
4611         {
4612                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4613                 if (FAILED(vsresult))
4614                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4615                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4616                 if (FAILED(psresult))
4617                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4618         }
4619         // free the shader data
4620         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4621         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4622 }
4623
4624 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4625 {
4626         int i;
4627         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4628         int vertstrings_count = 0, vertstring_length = 0;
4629         int geomstrings_count = 0, geomstring_length = 0;
4630         int fragstrings_count = 0, fragstring_length = 0;
4631         char *t;
4632         char *vertexstring, *geometrystring, *fragmentstring;
4633         char *vertstring, *geomstring, *fragstring;
4634         const char *vertstrings_list[32+3];
4635         const char *geomstrings_list[32+3];
4636         const char *fragstrings_list[32+3];
4637         char permutationname[256];
4638         char cachename[256];
4639
4640         if (p->compiled)
4641                 return;
4642         p->compiled = true;
4643         p->vertexshader = NULL;
4644         p->pixelshader = NULL;
4645
4646         permutationname[0] = 0;
4647         cachename[0] = 0;
4648         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4649         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4650         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4651
4652         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4653         strlcat(cachename, "hlsl/", sizeof(cachename));
4654
4655         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4656         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4657         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4658         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4659
4660         // the first pretext is which type of shader to compile as
4661         // (later these will all be bound together as a program object)
4662         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4663         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4664         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4665
4666         // the second pretext is the mode (for example a light source)
4667         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4668         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4669         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4670         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4671         strlcat(cachename, modeinfo->name, sizeof(cachename));
4672
4673         // now add all the permutation pretexts
4674         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4675         {
4676                 if (permutation & (1<<i))
4677                 {
4678                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4679                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4680                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4681                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4682                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4683                 }
4684                 else
4685                 {
4686                         // keep line numbers correct
4687                         vertstrings_list[vertstrings_count++] = "\n";
4688                         geomstrings_list[geomstrings_count++] = "\n";
4689                         fragstrings_list[fragstrings_count++] = "\n";
4690                 }
4691         }
4692
4693         // replace spaces in the cachename with _ characters
4694         for (i = 0;cachename[i];i++)
4695                 if (cachename[i] == ' ')
4696                         cachename[i] = '_';
4697
4698         // now append the shader text itself
4699         vertstrings_list[vertstrings_count++] = vertexstring;
4700         geomstrings_list[geomstrings_count++] = geometrystring;
4701         fragstrings_list[fragstrings_count++] = fragmentstring;
4702
4703         // if any sources were NULL, clear the respective list
4704         if (!vertexstring)
4705                 vertstrings_count = 0;
4706         if (!geometrystring)
4707                 geomstrings_count = 0;
4708         if (!fragmentstring)
4709                 fragstrings_count = 0;
4710
4711         vertstring_length = 0;
4712         for (i = 0;i < vertstrings_count;i++)
4713                 vertstring_length += strlen(vertstrings_list[i]);
4714         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4715         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4716                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4717
4718         geomstring_length = 0;
4719         for (i = 0;i < geomstrings_count;i++)
4720                 geomstring_length += strlen(geomstrings_list[i]);
4721         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4722         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4723                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4724
4725         fragstring_length = 0;
4726         for (i = 0;i < fragstrings_count;i++)
4727                 fragstring_length += strlen(fragstrings_list[i]);
4728         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4729         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4730                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4731
4732         // try to load the cached shader, or generate one
4733         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4734
4735         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4736                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4737         else
4738                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4739
4740         // free the strings
4741         if (vertstring)
4742                 Mem_Free(vertstring);
4743         if (geomstring)
4744                 Mem_Free(geomstring);
4745         if (fragstring)
4746                 Mem_Free(fragstring);
4747         if (vertexstring)
4748                 Mem_Free(vertexstring);
4749         if (geometrystring)
4750                 Mem_Free(geometrystring);
4751         if (fragmentstring)
4752                 Mem_Free(fragmentstring);
4753 }
4754
4755 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4756 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4757 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);}
4758 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);}
4759 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);}
4760 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);}
4761
4762 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4763 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4764 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);}
4765 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);}
4766 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);}
4767 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);}
4768
4769 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4770 {
4771         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4772         if (r_hlsl_permutation != perm)
4773         {
4774                 r_hlsl_permutation = perm;
4775                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4776                 {
4777                         if (!r_hlsl_permutation->compiled)
4778                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4779                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4780                         {
4781                                 // remove features until we find a valid permutation
4782                                 int i;
4783                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4784                                 {
4785                                         // reduce i more quickly whenever it would not remove any bits
4786                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4787                                         if (!(permutation & j))
4788                                                 continue;
4789                                         permutation -= j;
4790                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4791                                         if (!r_hlsl_permutation->compiled)
4792                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4793                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4794                                                 break;
4795                                 }
4796                                 if (i >= SHADERPERMUTATION_COUNT)
4797                                 {
4798                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4799                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4800                                         return; // no bit left to clear, entire mode is broken
4801                                 }
4802                         }
4803                 }
4804                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4805                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4806         }
4807         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4808         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4809         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4810 }
4811 #endif
4812
4813 void R_GLSL_Restart_f(void)
4814 {
4815         unsigned int i, limit;
4816         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4817                 Mem_Free(glslshaderstring);
4818         glslshaderstring = NULL;
4819         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4820                 Mem_Free(cgshaderstring);
4821         cgshaderstring = NULL;
4822         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4823                 Mem_Free(hlslshaderstring);
4824         hlslshaderstring = NULL;
4825         switch(vid.renderpath)
4826         {
4827         case RENDERPATH_D3D9:
4828 #ifdef SUPPORTD3D
4829                 {
4830                         r_hlsl_permutation_t *p;
4831                         r_hlsl_permutation = NULL;
4832 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4833 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4834 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4835 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4836                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4837                         for (i = 0;i < limit;i++)
4838                         {
4839                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4840                                 {
4841                                         if (p->vertexshader)
4842                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4843                                         if (p->pixelshader)
4844                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4845                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4846                                 }
4847                         }
4848                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4849                 }
4850 #endif
4851                 break;
4852         case RENDERPATH_D3D10:
4853                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4854                 break;
4855         case RENDERPATH_D3D11:
4856                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4857                 break;
4858         case RENDERPATH_GL20:
4859                 {
4860                         r_glsl_permutation_t *p;
4861                         r_glsl_permutation = NULL;
4862                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4863                         for (i = 0;i < limit;i++)
4864                         {
4865                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4866                                 {
4867                                         GL_Backend_FreeProgram(p->program);
4868                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4869                                 }
4870                         }
4871                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4872                 }
4873                 break;
4874         case RENDERPATH_CGGL:
4875 #ifdef SUPPORTCG
4876                 {
4877                         r_cg_permutation_t *p;
4878                         r_cg_permutation = NULL;
4879                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4880                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4881                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4882                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4883                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4884                         for (i = 0;i < limit;i++)
4885                         {
4886                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4887                                 {
4888                                         if (p->vprogram)
4889                                                 cgDestroyProgram(p->vprogram);
4890                                         if (p->fprogram)
4891                                                 cgDestroyProgram(p->fprogram);
4892                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4893                                 }
4894                         }
4895                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4896                 }
4897 #endif
4898                 break;
4899         case RENDERPATH_GL13:
4900         case RENDERPATH_GL11:
4901                 break;
4902         }
4903 }
4904
4905 void R_GLSL_DumpShader_f(void)
4906 {
4907         int i;
4908         qfile_t *file;
4909
4910         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4911         if (file)
4912         {
4913                 FS_Print(file, "/* The engine may define the following macros:\n");
4914                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4915                 for (i = 0;i < SHADERMODE_COUNT;i++)
4916                         FS_Print(file, glslshadermodeinfo[i].pretext);
4917                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4918                         FS_Print(file, shaderpermutationinfo[i].pretext);
4919                 FS_Print(file, "*/\n");
4920                 FS_Print(file, builtinshaderstring);
4921                 FS_Close(file);
4922                 Con_Printf("glsl/default.glsl written\n");
4923         }
4924         else
4925                 Con_Printf("failed to write to glsl/default.glsl\n");
4926
4927 #ifdef SUPPORTCG
4928         file = FS_OpenRealFile("cg/default.cg", "w", false);
4929         if (file)
4930         {
4931                 FS_Print(file, "/* The engine may define the following macros:\n");
4932                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4933                 for (i = 0;i < SHADERMODE_COUNT;i++)
4934                         FS_Print(file, cgshadermodeinfo[i].pretext);
4935                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4936                         FS_Print(file, shaderpermutationinfo[i].pretext);
4937                 FS_Print(file, "*/\n");
4938                 FS_Print(file, builtincgshaderstring);
4939                 FS_Close(file);
4940                 Con_Printf("cg/default.cg written\n");
4941         }
4942         else
4943                 Con_Printf("failed to write to cg/default.cg\n");
4944 #endif
4945
4946 #ifdef SUPPORTD3D
4947         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4948         if (file)
4949         {
4950                 FS_Print(file, "/* The engine may define the following macros:\n");
4951                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4952                 for (i = 0;i < SHADERMODE_COUNT;i++)
4953                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4954                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4955                         FS_Print(file, shaderpermutationinfo[i].pretext);
4956                 FS_Print(file, "*/\n");
4957                 FS_Print(file, builtincgshaderstring);
4958                 FS_Close(file);
4959                 Con_Printf("hlsl/default.hlsl written\n");
4960         }
4961         else
4962                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4963 #endif
4964 }
4965
4966 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4967 {
4968         if (!second)
4969                 texturemode = GL_MODULATE;
4970         switch (vid.renderpath)
4971         {
4972         case RENDERPATH_D3D9:
4973 #ifdef SUPPORTD3D
4974                 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))));
4975                 R_Mesh_TexBind(GL20TU_FIRST , first );
4976                 R_Mesh_TexBind(GL20TU_SECOND, second);
4977 #endif
4978                 break;
4979         case RENDERPATH_D3D10:
4980                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4981                 break;
4982         case RENDERPATH_D3D11:
4983                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4984                 break;
4985         case RENDERPATH_GL20:
4986                 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))));
4987                 R_Mesh_TexBind(GL20TU_FIRST , first );
4988                 R_Mesh_TexBind(GL20TU_SECOND, second);
4989                 break;
4990         case RENDERPATH_CGGL:
4991 #ifdef SUPPORTCG
4992                 CHECKCGERROR
4993                 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))));
4994                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4995                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4996 #endif
4997                 break;
4998         case RENDERPATH_GL13:
4999                 R_Mesh_TexBind(0, first );
5000                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5001                 R_Mesh_TexBind(1, second);
5002                 if (second)
5003                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5004                 break;
5005         case RENDERPATH_GL11:
5006                 R_Mesh_TexBind(0, first );
5007                 break;
5008         }
5009 }
5010
5011 void R_SetupShader_DepthOrShadow(void)
5012 {
5013         switch (vid.renderpath)
5014         {
5015         case RENDERPATH_D3D9:
5016 #ifdef SUPPORTD3D
5017                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5018 #endif
5019                 break;
5020         case RENDERPATH_D3D10:
5021                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5022                 break;
5023         case RENDERPATH_D3D11:
5024                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5025                 break;
5026         case RENDERPATH_GL20:
5027                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5028                 break;
5029         case RENDERPATH_CGGL:
5030 #ifdef SUPPORTCG
5031                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5032 #endif
5033                 break;
5034         case RENDERPATH_GL13:
5035                 R_Mesh_TexBind(0, 0);
5036                 R_Mesh_TexBind(1, 0);
5037                 break;
5038         case RENDERPATH_GL11:
5039                 R_Mesh_TexBind(0, 0);
5040                 break;
5041         }
5042 }
5043
5044 void R_SetupShader_ShowDepth(void)
5045 {
5046         switch (vid.renderpath)
5047         {
5048         case RENDERPATH_D3D9:
5049 #ifdef SUPPORTHLSL
5050                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5051 #endif
5052                 break;
5053         case RENDERPATH_D3D10:
5054                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5055                 break;
5056         case RENDERPATH_D3D11:
5057                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5058                 break;
5059         case RENDERPATH_GL20:
5060                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5061                 break;
5062         case RENDERPATH_CGGL:
5063 #ifdef SUPPORTCG
5064                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5065 #endif
5066                 break;
5067         case RENDERPATH_GL13:
5068                 break;
5069         case RENDERPATH_GL11:
5070                 break;
5071         }
5072 }
5073
5074 extern qboolean r_shadow_usingdeferredprepass;
5075 extern cvar_t r_shadow_deferred_8bitrange;
5076 extern rtexture_t *r_shadow_attenuationgradienttexture;
5077 extern rtexture_t *r_shadow_attenuation2dtexture;
5078 extern rtexture_t *r_shadow_attenuation3dtexture;
5079 extern qboolean r_shadow_usingshadowmap2d;
5080 extern qboolean r_shadow_usingshadowmaportho;
5081 extern float r_shadow_shadowmap_texturescale[2];
5082 extern float r_shadow_shadowmap_parameters[4];
5083 extern qboolean r_shadow_shadowmapvsdct;
5084 extern qboolean r_shadow_shadowmapsampler;
5085 extern int r_shadow_shadowmappcf;
5086 extern rtexture_t *r_shadow_shadowmap2dtexture;
5087 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5088 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5089 extern matrix4x4_t r_shadow_shadowmapmatrix;
5090 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5091 extern int r_shadow_prepass_width;
5092 extern int r_shadow_prepass_height;
5093 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5094 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5095 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5096 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5097 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5098 extern cvar_t gl_mesh_separatearrays;
5099 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5100 {
5101         // a blendfunc allows colormod if:
5102         // a) it can never keep the destination pixel invariant, or
5103         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5104         // this is to prevent unintended side effects from colormod
5105
5106         // in formulas:
5107         // IF there is a (s, sa) for which for all (d, da),
5108         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5109         // THEN, for this (s, sa) and all (colormod, d, da):
5110         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5111         // OBVIOUSLY, this means that
5112         //   s*colormod * src(s*colormod, d, sa, da) = 0
5113         //   dst(s*colormod, d, sa, da)              = 1
5114
5115         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5116
5117         // main condition to leave dst color invariant:
5118         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5119         //   src == GL_ZERO:
5120         //     s * 0 + d * dst(s, d, sa, da) == d
5121         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5122         //       => colormod is a problem for GL_SRC_COLOR only
5123         //   src == GL_ONE:
5124         //     s + d * dst(s, d, sa, da) == d
5125         //       => s == 0
5126         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5127         //       => colormod is never problematic for these
5128         //   src == GL_SRC_COLOR:
5129         //     s*s + d * dst(s, d, sa, da) == d
5130         //       => s == 0
5131         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5132         //       => colormod is never problematic for these
5133         //   src == GL_ONE_MINUS_SRC_COLOR:
5134         //     s*(1-s) + d * dst(s, d, sa, da) == d
5135         //       => s == 0 or s == 1
5136         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5137         //       => colormod is a problem for GL_SRC_COLOR only
5138         //   src == GL_DST_COLOR
5139         //     s*d + d * dst(s, d, sa, da) == d
5140         //       => s == 1
5141         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5142         //       => colormod is always a problem
5143         //     or
5144         //       => s == 0
5145         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5146         //       => colormod is never problematic for these
5147         //       => BUT, we do not know s! We must assume it is problematic
5148         //       then... except in GL_ONE case, where we know all invariant
5149         //       cases are fine
5150         //   src == GL_ONE_MINUS_DST_COLOR
5151         //     s*(1-d) + d * dst(s, d, sa, da) == d
5152         //       => s == 0 (1-d is impossible to handle for our desired result)
5153         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5154         //       => colormod is never problematic for these
5155         //   src == GL_SRC_ALPHA
5156         //     s*sa + d * dst(s, d, sa, da) == d
5157         //       => s == 0, or sa == 0
5158         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5159         //       => colormod breaks in the case GL_SRC_COLOR only
5160         //   src == GL_ONE_MINUS_SRC_ALPHA
5161         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5162         //       => s == 0, or sa == 1
5163         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5164         //       => colormod breaks in the case GL_SRC_COLOR only
5165         //   src == GL_DST_ALPHA
5166         //     s*da + d * dst(s, d, sa, da) == d
5167         //       => s == 0
5168         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5169         //       => colormod is never problematic for these
5170
5171         switch(src)
5172         {
5173                 case GL_ZERO:
5174                 case GL_ONE_MINUS_SRC_COLOR:
5175                 case GL_SRC_ALPHA:
5176                 case GL_ONE_MINUS_SRC_ALPHA:
5177                         if(dst == GL_SRC_COLOR)
5178                                 return false;
5179                         return true;
5180                 case GL_ONE:
5181                 case GL_SRC_COLOR:
5182                 case GL_ONE_MINUS_DST_COLOR:
5183                 case GL_DST_ALPHA:
5184                 case GL_ONE_MINUS_DST_ALPHA:
5185                         return true;
5186                 case GL_DST_COLOR:
5187                         if(dst == GL_ONE)
5188                                 return true;
5189                         return false;
5190                 default:
5191                         return false;
5192         }
5193 }
5194 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)
5195 {
5196         // select a permutation of the lighting shader appropriate to this
5197         // combination of texture, entity, light source, and fogging, only use the
5198         // minimum features necessary to avoid wasting rendering time in the
5199         // fragment shader on features that are not being used
5200         unsigned int permutation = 0;
5201         unsigned int mode = 0;
5202         qboolean allow_colormod;
5203         static float dummy_colormod[3] = {1, 1, 1};
5204         float *colormod = rsurface.colormod;
5205         float m16f[16];
5206         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5207         if (rsurfacepass == RSURFPASS_BACKGROUND)
5208         {
5209                 // distorted background
5210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5211                         mode = SHADERMODE_WATER;
5212                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5213                         mode = SHADERMODE_REFRACTION;
5214                 else
5215                 {
5216                         mode = SHADERMODE_GENERIC;
5217                         permutation |= SHADERPERMUTATION_DIFFUSE;
5218                 }
5219                 GL_AlphaTest(false);
5220                 GL_BlendFunc(GL_ONE, GL_ZERO);
5221                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5222         }
5223         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5224         {
5225                 if (r_glsl_offsetmapping.integer)
5226                 {
5227                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5228                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5229                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5230                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5231                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5232                         {
5233                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5234                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5235                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5236                         }
5237                 }
5238                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5239                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5240                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5241                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5242                 // normalmap (deferred prepass), may use alpha test on diffuse
5243                 mode = SHADERMODE_DEFERREDGEOMETRY;
5244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5246                 GL_AlphaTest(false);
5247                 GL_BlendFunc(GL_ONE, GL_ZERO);
5248                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5249         }
5250         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5251         {
5252                 if (r_glsl_offsetmapping.integer)
5253                 {
5254                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5255                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5256                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5257                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5258                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5259                         {
5260                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5261                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5262                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5263                         }
5264                 }
5265                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5266                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5267                 // light source
5268                 mode = SHADERMODE_LIGHTSOURCE;
5269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5271                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5272                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5273                 if (diffusescale > 0)
5274                         permutation |= SHADERPERMUTATION_DIFFUSE;
5275                 if (specularscale > 0)
5276                 {
5277                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5278                         if (r_shadow_glossexact.integer)
5279                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5280                 }
5281                 if (r_refdef.fogenabled)
5282                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5283                 if (rsurface.texture->colormapping)
5284                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5285                 if (r_shadow_usingshadowmap2d)
5286                 {
5287                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5288                         if(r_shadow_shadowmapvsdct)
5289                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5290
5291                         if (r_shadow_shadowmapsampler)
5292                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5293                         if (r_shadow_shadowmappcf > 1)
5294                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5295                         else if (r_shadow_shadowmappcf)
5296                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5297                 }
5298                 if (rsurface.texture->reflectmasktexture)
5299                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5300                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5301                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5302                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5303         }
5304         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5305         {
5306                 if (r_glsl_offsetmapping.integer)
5307                 {
5308                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5309                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5310                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5311                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5312                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5313                         {
5314                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5315                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5316                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5317                         }
5318                 }
5319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5320                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5321                 // unshaded geometry (fullbright or ambient model lighting)
5322                 mode = SHADERMODE_FLATCOLOR;
5323                 ambientscale = diffusescale = specularscale = 0;
5324                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5325                         permutation |= SHADERPERMUTATION_GLOW;
5326                 if (r_refdef.fogenabled)
5327                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5328                 if (rsurface.texture->colormapping)
5329                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5330                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5331                 {
5332                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5333                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5334
5335                         if (r_shadow_shadowmapsampler)
5336                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5337                         if (r_shadow_shadowmappcf > 1)
5338                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5339                         else if (r_shadow_shadowmappcf)
5340                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5341                 }
5342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5343                         permutation |= SHADERPERMUTATION_REFLECTION;
5344                 if (rsurface.texture->reflectmasktexture)
5345                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5346                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5347                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5348                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5349         }
5350         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5351         {
5352                 if (r_glsl_offsetmapping.integer)
5353                 {
5354                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5355                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5356                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5357                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5358                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5359                         {
5360                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5361                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5362                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5363                         }
5364                 }
5365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5366                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5367                 // directional model lighting
5368                 mode = SHADERMODE_LIGHTDIRECTION;
5369                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5370                         permutation |= SHADERPERMUTATION_GLOW;
5371                 permutation |= SHADERPERMUTATION_DIFFUSE;
5372                 if (specularscale > 0)
5373                 {
5374                         permutation |= SHADERPERMUTATION_SPECULAR;
5375                         if (r_shadow_glossexact.integer)
5376                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5377                 }
5378                 if (r_refdef.fogenabled)
5379                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5380                 if (rsurface.texture->colormapping)
5381                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5382                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5383                 {
5384                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5385                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5386
5387                         if (r_shadow_shadowmapsampler)
5388                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5389                         if (r_shadow_shadowmappcf > 1)
5390                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5391                         else if (r_shadow_shadowmappcf)
5392                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5393                 }
5394                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5395                         permutation |= SHADERPERMUTATION_REFLECTION;
5396                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5397                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5398                 if (rsurface.texture->reflectmasktexture)
5399                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5400                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5401                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5402                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5403         }
5404         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5405         {
5406                 if (r_glsl_offsetmapping.integer)
5407                 {
5408                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5409                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5410                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5411                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5412                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5413                         {
5414                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5415                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5416                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5417                         }
5418                 }
5419                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5420                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5421                 // ambient model lighting
5422                 mode = SHADERMODE_LIGHTDIRECTION;
5423                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5424                         permutation |= SHADERPERMUTATION_GLOW;
5425                 if (r_refdef.fogenabled)
5426                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5427                 if (rsurface.texture->colormapping)
5428                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5429                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5430                 {
5431                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5432                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5433
5434                         if (r_shadow_shadowmapsampler)
5435                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5436                         if (r_shadow_shadowmappcf > 1)
5437                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5438                         else if (r_shadow_shadowmappcf)
5439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5440                 }
5441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5442                         permutation |= SHADERPERMUTATION_REFLECTION;
5443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5445                 if (rsurface.texture->reflectmasktexture)
5446                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5447                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5448                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5449                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5450         }
5451         else
5452         {
5453                 if (r_glsl_offsetmapping.integer)
5454                 {
5455                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5456                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5457                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5459                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5460                         {
5461                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5462                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5463                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5464                         }
5465                 }
5466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5467                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5468                 // lightmapped wall
5469                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5470                         permutation |= SHADERPERMUTATION_GLOW;
5471                 if (r_refdef.fogenabled)
5472                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5473                 if (rsurface.texture->colormapping)
5474                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5475                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5476                 {
5477                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5478                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5479
5480                         if (r_shadow_shadowmapsampler)
5481                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5482                         if (r_shadow_shadowmappcf > 1)
5483                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5484                         else if (r_shadow_shadowmappcf)
5485                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5486                 }
5487                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5488                         permutation |= SHADERPERMUTATION_REFLECTION;
5489                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5490                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5491                 if (rsurface.texture->reflectmasktexture)
5492                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5493                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5494                 {
5495                         // deluxemapping (light direction texture)
5496                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5497                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5498                         else
5499                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5500                         permutation |= SHADERPERMUTATION_DIFFUSE;
5501                         if (specularscale > 0)
5502                         {
5503                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5504                                 if (r_shadow_glossexact.integer)
5505                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5506                         }
5507                 }
5508                 else if (r_glsl_deluxemapping.integer >= 2)
5509                 {
5510                         // fake deluxemapping (uniform light direction in tangentspace)
5511                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5512                         permutation |= SHADERPERMUTATION_DIFFUSE;
5513                         if (specularscale > 0)
5514                         {
5515                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5516                                 if (r_shadow_glossexact.integer)
5517                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5518                         }
5519                 }
5520                 else if (rsurface.uselightmaptexture)
5521                 {
5522                         // ordinary lightmapping (q1bsp, q3bsp)
5523                         mode = SHADERMODE_LIGHTMAP;
5524                 }
5525                 else
5526                 {
5527                         // ordinary vertex coloring (q3bsp)
5528                         mode = SHADERMODE_VERTEXCOLOR;
5529                 }
5530                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5531                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5532                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5533         }
5534         if(!allow_colormod)
5535                 colormod = dummy_colormod;
5536         switch(vid.renderpath)
5537         {
5538         case RENDERPATH_D3D9:
5539 #ifdef SUPPORTD3D
5540                 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);
5541                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5542                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5543                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5544                 if (mode == SHADERMODE_LIGHTSOURCE)
5545                 {
5546                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5547                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5548                 }
5549                 else
5550                 {
5551                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5552                         {
5553                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5554                         }
5555                 }
5556                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5557                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5558                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5559                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5560                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5561
5562                 if (mode == SHADERMODE_LIGHTSOURCE)
5563                 {
5564                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5565                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5567                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5569
5570                         // additive passes are only darkened by fog, not tinted
5571                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5572                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5573                 }
5574                 else
5575                 {
5576                         if (mode == SHADERMODE_FLATCOLOR)
5577                         {
5578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5579                         }
5580                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5581                         {
5582                                 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]);
5583                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5584                                 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);
5585                                 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);
5586                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5587                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5588                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5589                         }
5590                         else
5591                         {
5592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5594                                 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);
5595                                 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);
5596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5597                         }
5598                         // additive passes are only darkened by fog, not tinted
5599                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5600                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5601                         else
5602                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5603                         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);
5604                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5605                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5606                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5607                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5608                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5609                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5610                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5611                 }
5612                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5613                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5614                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5615                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5616                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5617                 if (rsurface.texture->pantstexture)
5618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5619                 else
5620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5621                 if (rsurface.texture->shirttexture)
5622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5623                 else
5624                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5625                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5626                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5627                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5628                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5629                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5630                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5631                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5632
5633                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5634                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5635                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5636                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5637                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5638                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5641                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5642                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5643                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5644                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5645                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5646                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5647                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5648                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5649                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5650                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5651                 {
5652                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5653                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5654                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5655                 }
5656                 else
5657                 {
5658                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5659                 }
5660 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5661 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5662                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5663                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5664                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5665                 {
5666                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5667                         if (rsurface.rtlight)
5668                         {
5669                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5670                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5671                         }
5672                 }
5673 #endif
5674                 break;
5675         case RENDERPATH_D3D10:
5676                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5677                 break;
5678         case RENDERPATH_D3D11:
5679                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5680                 break;
5681         case RENDERPATH_GL20:
5682                 if (gl_mesh_separatearrays.integer)
5683                 {
5684                         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);
5685                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5686                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5687                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5688                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5689                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5690                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5691                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5692                 }
5693                 else
5694                 {
5695                         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);
5696                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5697                 }
5698                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5699                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5700                 if (mode == SHADERMODE_LIGHTSOURCE)
5701                 {
5702                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5703                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5704                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5705                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5706                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5707                         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);
5708         
5709                         // additive passes are only darkened by fog, not tinted
5710                         if (r_glsl_permutation->loc_FogColor >= 0)
5711                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5712                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5713                 }
5714                 else
5715                 {
5716                         if (mode == SHADERMODE_FLATCOLOR)
5717                         {
5718                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5719                         }
5720                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5721                         {
5722                                 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]);
5723                                 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]);
5724                                 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);
5725                                 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);
5726                                 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);
5727                                 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]);
5728                                 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]);
5729                         }
5730                         else
5731                         {
5732                                 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]);
5733                                 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]);
5734                                 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);
5735                                 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);
5736                                 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);
5737                         }
5738                         // additive passes are only darkened by fog, not tinted
5739                         if (r_glsl_permutation->loc_FogColor >= 0)
5740                         {
5741                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5742                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5743                                 else
5744                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5745                         }
5746                         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);
5747                         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]);
5748                         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]);
5749                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5750                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5751                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5752                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5753                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5754                 }
5755                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5756                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5757                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5758                 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]);
5759                 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]);
5760
5761                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5762                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5763                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5764                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5765                 {
5766                         if (rsurface.texture->pantstexture)
5767                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5768                         else
5769                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5770                 }
5771                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5772                 {
5773                         if (rsurface.texture->shirttexture)
5774                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5775                         else
5776                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5777                 }
5778                 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]);
5779                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5780                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5781                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5782                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5783                 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]);
5784                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5785
5786         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5787         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5788         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5789                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5790                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5791                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5792                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5793                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5794                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5795                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5796                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5797                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5798                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5799                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5800                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5801                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5802                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5803                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5804                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5805                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5806                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5807                 {
5808                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5809                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5810                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5811                 }
5812                 else
5813                 {
5814                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5815                 }
5816 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5817 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5818                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5819                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5820                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5821                 {
5822                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5823                         if (rsurface.rtlight)
5824                         {
5825                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5826                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5827                         }
5828                 }
5829                 CHECKGLERROR
5830                 break;
5831         case RENDERPATH_CGGL:
5832 #ifdef SUPPORTCG
5833                 if (gl_mesh_separatearrays.integer)
5834                 {
5835                         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);
5836                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5837                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5838                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5839                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5840                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5841                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5842                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5843                 }
5844                 else
5845                 {
5846                         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);
5847                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5848                 }
5849                 R_SetupShader_SetPermutationCG(mode, permutation);
5850                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5851                 if (mode == SHADERMODE_LIGHTSOURCE)
5852                 {
5853                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5854                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5855                 }
5856                 else
5857                 {
5858                         if (mode == SHADERMODE_LIGHTDIRECTION)
5859                         {
5860                                 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
5861                         }
5862                 }
5863                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5864                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5865                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5866                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5867                 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
5868                 CHECKGLERROR
5869
5870                 if (mode == SHADERMODE_LIGHTSOURCE)
5871                 {
5872                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5873                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5874                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5875                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5876                         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
5877
5878                         // additive passes are only darkened by fog, not tinted
5879                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5880                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5881                 }
5882                 else
5883                 {
5884                         if (mode == SHADERMODE_FLATCOLOR)
5885                         {
5886                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5887                         }
5888                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5889                         {
5890                                 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
5891                                 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
5892                                 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
5893                                 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
5894                                 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
5895                                 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
5896                                 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
5897                         }
5898                         else
5899                         {
5900                                 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
5901                                 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
5902                                 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
5903                                 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
5904                                 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
5905                         }
5906                         // additive passes are only darkened by fog, not tinted
5907                         if (r_cg_permutation->fp_FogColor)
5908                         {
5909                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5910                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5911                                 else
5912                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5913                                 CHECKCGERROR
5914                         }
5915                         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
5916                         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
5917                         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
5918                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5919                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5920                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5921                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5922                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5923                 }
5924                 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
5925                 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
5926                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5927                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5928                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5929                 if (r_cg_permutation->fp_Color_Pants)
5930                 {
5931                         if (rsurface.texture->pantstexture)
5932                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5933                         else
5934                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5935                         CHECKCGERROR
5936                 }
5937                 if (r_cg_permutation->fp_Color_Shirt)
5938                 {
5939                         if (rsurface.texture->shirttexture)
5940                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5941                         else
5942                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5943                         CHECKCGERROR
5944                 }
5945                 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
5946                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5947                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5948                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5949                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5950                 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
5951                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5952
5953         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5954         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5955         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5956                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5957                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5958                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5959                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5960                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5961                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5962                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5963                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5964                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5965                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5966                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5967                 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
5968                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5969                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5970                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5971                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5972                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5973                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5974                 {
5975                         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
5976                         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
5977                         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
5978                 }
5979                 else
5980                 {
5981                         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
5982                 }
5983                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5984                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5985                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5986                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5987                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5988                 {
5989                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5990                         if (rsurface.rtlight)
5991                         {
5992                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5993                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5994                         }
5995                 }
5996
5997                 CHECKGLERROR
5998 #endif
5999                 break;
6000         case RENDERPATH_GL13:
6001         case RENDERPATH_GL11:
6002                 break;
6003         }
6004 }
6005
6006 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6007 {
6008         // select a permutation of the lighting shader appropriate to this
6009         // combination of texture, entity, light source, and fogging, only use the
6010         // minimum features necessary to avoid wasting rendering time in the
6011         // fragment shader on features that are not being used
6012         unsigned int permutation = 0;
6013         unsigned int mode = 0;
6014         const float *lightcolorbase = rtlight->currentcolor;
6015         float ambientscale = rtlight->ambientscale;
6016         float diffusescale = rtlight->diffusescale;
6017         float specularscale = rtlight->specularscale;
6018         // this is the location of the light in view space
6019         vec3_t viewlightorigin;
6020         // this transforms from view space (camera) to light space (cubemap)
6021         matrix4x4_t viewtolight;
6022         matrix4x4_t lighttoview;
6023         float viewtolight16f[16];
6024         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6025         // light source
6026         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6027         if (rtlight->currentcubemap != r_texture_whitecube)
6028                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6029         if (diffusescale > 0)
6030                 permutation |= SHADERPERMUTATION_DIFFUSE;
6031         if (specularscale > 0)
6032         {
6033                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6034                 if (r_shadow_glossexact.integer)
6035                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6036         }
6037         if (r_shadow_usingshadowmap2d)
6038         {
6039                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6040                 if (r_shadow_shadowmapvsdct)
6041                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6042
6043                 if (r_shadow_shadowmapsampler)
6044                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6045                 if (r_shadow_shadowmappcf > 1)
6046                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6047                 else if (r_shadow_shadowmappcf)
6048                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6049         }
6050         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6051         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6052         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6053         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6054         switch(vid.renderpath)
6055         {
6056         case RENDERPATH_D3D9:
6057 #ifdef SUPPORTD3D
6058                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6059                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6060                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6061                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6062                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6063                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6064                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6065                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6066                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6067                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6068                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6069
6070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6071                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6072                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6073                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6074                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6075                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6076 #endif
6077                 break;
6078         case RENDERPATH_D3D10:
6079                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6080                 break;
6081         case RENDERPATH_D3D11:
6082                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6083                 break;
6084         case RENDERPATH_GL20:
6085                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6086                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6087                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6088                 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);
6089                 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);
6090                 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);
6091                 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]);
6092                 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]);
6093                 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));
6094                 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]);
6095                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6096
6097                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6098                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6099                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6100                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6101                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6102                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6103                 break;
6104         case RENDERPATH_CGGL:
6105 #ifdef SUPPORTCG
6106                 R_SetupShader_SetPermutationCG(mode, permutation);
6107                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6108                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6109                 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
6110                 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
6111                 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
6112                 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
6113                 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
6114                 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
6115                 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
6116                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6117
6118                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6119                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6120                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6121                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6122                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6123                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6124 #endif
6125                 break;
6126         case RENDERPATH_GL13:
6127         case RENDERPATH_GL11:
6128                 break;
6129         }
6130 }
6131
6132 #define SKINFRAME_HASH 1024
6133
6134 typedef struct
6135 {
6136         int loadsequence; // incremented each level change
6137         memexpandablearray_t array;
6138         skinframe_t *hash[SKINFRAME_HASH];
6139 }
6140 r_skinframe_t;
6141 r_skinframe_t r_skinframe;
6142
6143 void R_SkinFrame_PrepareForPurge(void)
6144 {
6145         r_skinframe.loadsequence++;
6146         // wrap it without hitting zero
6147         if (r_skinframe.loadsequence >= 200)
6148                 r_skinframe.loadsequence = 1;
6149 }
6150
6151 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6152 {
6153         if (!skinframe)
6154                 return;
6155         // mark the skinframe as used for the purging code
6156         skinframe->loadsequence = r_skinframe.loadsequence;
6157 }
6158
6159 void R_SkinFrame_Purge(void)
6160 {
6161         int i;
6162         skinframe_t *s;
6163         for (i = 0;i < SKINFRAME_HASH;i++)
6164         {
6165                 for (s = r_skinframe.hash[i];s;s = s->next)
6166                 {
6167                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6168                         {
6169                                 if (s->merged == s->base)
6170                                         s->merged = NULL;
6171                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6172                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6173                                 R_PurgeTexture(s->merged);s->merged = NULL;
6174                                 R_PurgeTexture(s->base  );s->base   = NULL;
6175                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6176                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6177                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6178                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6179                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6180                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6181                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6182                                 s->loadsequence = 0;
6183                         }
6184                 }
6185         }
6186 }
6187
6188 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6189         skinframe_t *item;
6190         char basename[MAX_QPATH];
6191
6192         Image_StripImageExtension(name, basename, sizeof(basename));
6193
6194         if( last == NULL ) {
6195                 int hashindex;
6196                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6197                 item = r_skinframe.hash[hashindex];
6198         } else {
6199                 item = last->next;
6200         }
6201
6202         // linearly search through the hash bucket
6203         for( ; item ; item = item->next ) {
6204                 if( !strcmp( item->basename, basename ) ) {
6205                         return item;
6206                 }
6207         }
6208         return NULL;
6209 }
6210
6211 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6212 {
6213         skinframe_t *item;
6214         int hashindex;
6215         char basename[MAX_QPATH];
6216
6217         Image_StripImageExtension(name, basename, sizeof(basename));
6218
6219         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6220         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6221                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6222                         break;
6223
6224         if (!item) {
6225                 rtexture_t *dyntexture;
6226                 // check whether its a dynamic texture
6227                 dyntexture = CL_GetDynTexture( basename );
6228                 if (!add && !dyntexture)
6229                         return NULL;
6230                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6231                 memset(item, 0, sizeof(*item));
6232                 strlcpy(item->basename, basename, sizeof(item->basename));
6233                 item->base = dyntexture; // either NULL or dyntexture handle
6234                 item->textureflags = textureflags;
6235                 item->comparewidth = comparewidth;
6236                 item->compareheight = compareheight;
6237                 item->comparecrc = comparecrc;
6238                 item->next = r_skinframe.hash[hashindex];
6239                 r_skinframe.hash[hashindex] = item;
6240         }
6241         else if( item->base == NULL )
6242         {
6243                 rtexture_t *dyntexture;
6244                 // check whether its a dynamic texture
6245                 // 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]
6246                 dyntexture = CL_GetDynTexture( basename );
6247                 item->base = dyntexture; // either NULL or dyntexture handle
6248         }
6249
6250         R_SkinFrame_MarkUsed(item);
6251         return item;
6252 }
6253
6254 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6255         { \
6256                 unsigned long long avgcolor[5], wsum; \
6257                 int pix, comp, w; \
6258                 avgcolor[0] = 0; \
6259                 avgcolor[1] = 0; \
6260                 avgcolor[2] = 0; \
6261                 avgcolor[3] = 0; \
6262                 avgcolor[4] = 0; \
6263                 wsum = 0; \
6264                 for(pix = 0; pix < cnt; ++pix) \
6265                 { \
6266                         w = 0; \
6267                         for(comp = 0; comp < 3; ++comp) \
6268                                 w += getpixel; \
6269                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6270                         { \
6271                                 ++wsum; \
6272                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6273                                 w = getpixel; \
6274                                 for(comp = 0; comp < 3; ++comp) \
6275                                         avgcolor[comp] += getpixel * w; \
6276                                 avgcolor[3] += w; \
6277                         } \
6278                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6279                         avgcolor[4] += getpixel; \
6280                 } \
6281                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6282                         avgcolor[3] = 1; \
6283                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6284                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6285                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6286                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6287         }
6288
6289 extern cvar_t gl_picmip;
6290 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6291 {
6292         int j;
6293         unsigned char *pixels;
6294         unsigned char *bumppixels;
6295         unsigned char *basepixels = NULL;
6296         int basepixels_width = 0;
6297         int basepixels_height = 0;
6298         skinframe_t *skinframe;
6299         rtexture_t *ddsbase = NULL;
6300         qboolean ddshasalpha = false;
6301         float ddsavgcolor[4];
6302         char basename[MAX_QPATH];
6303         int miplevel = R_PicmipForFlags(textureflags);
6304         int savemiplevel = miplevel;
6305         int mymiplevel;
6306
6307         if (cls.state == ca_dedicated)
6308                 return NULL;
6309
6310         // return an existing skinframe if already loaded
6311         // if loading of the first image fails, don't make a new skinframe as it
6312         // would cause all future lookups of this to be missing
6313         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6314         if (skinframe && skinframe->base)
6315                 return skinframe;
6316
6317         Image_StripImageExtension(name, basename, sizeof(basename));
6318
6319         // check for DDS texture file first
6320         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6321         {
6322                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6323                 if (basepixels == NULL)
6324                         return NULL;
6325         }
6326
6327         // FIXME handle miplevel
6328
6329         if (developer_loading.integer)
6330                 Con_Printf("loading skin \"%s\"\n", name);
6331
6332         // we've got some pixels to store, so really allocate this new texture now
6333         if (!skinframe)
6334                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6335         skinframe->stain = NULL;
6336         skinframe->merged = NULL;
6337         skinframe->base = NULL;
6338         skinframe->pants = NULL;
6339         skinframe->shirt = NULL;
6340         skinframe->nmap = NULL;
6341         skinframe->gloss = NULL;
6342         skinframe->glow = NULL;
6343         skinframe->fog = NULL;
6344         skinframe->reflect = NULL;
6345         skinframe->hasalpha = false;
6346
6347         if (ddsbase)
6348         {
6349                 skinframe->base = ddsbase;
6350                 skinframe->hasalpha = ddshasalpha;
6351                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6352                 if (r_loadfog && skinframe->hasalpha)
6353                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6354                 //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]);
6355         }
6356         else
6357         {
6358                 basepixels_width = image_width;
6359                 basepixels_height = image_height;
6360                 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);
6361                 if (textureflags & TEXF_ALPHA)
6362                 {
6363                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6364                         {
6365                                 if (basepixels[j] < 255)
6366                                 {
6367                                         skinframe->hasalpha = true;
6368                                         break;
6369                                 }
6370                         }
6371                         if (r_loadfog && skinframe->hasalpha)
6372                         {
6373                                 // has transparent pixels
6374                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6375                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6376                                 {
6377                                         pixels[j+0] = 255;
6378                                         pixels[j+1] = 255;
6379                                         pixels[j+2] = 255;
6380                                         pixels[j+3] = basepixels[j+3];
6381                                 }
6382                                 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);
6383                                 Mem_Free(pixels);
6384                         }
6385                 }
6386                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6387                 //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]);
6388                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6389                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6391                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6392         }
6393
6394         if (r_loaddds)
6395         {
6396                 mymiplevel = savemiplevel;
6397                 if (r_loadnormalmap)
6398                         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);
6399                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6400                 if (r_loadgloss)
6401                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6402                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6403                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6404                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6405         }
6406
6407         // _norm is the name used by tenebrae and has been adopted as standard
6408         if (r_loadnormalmap && skinframe->nmap == NULL)
6409         {
6410                 mymiplevel = savemiplevel;
6411                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6412                 {
6413                         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);
6414                         Mem_Free(pixels);
6415                         pixels = NULL;
6416                 }
6417                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6418                 {
6419                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6420                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6421                         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);
6422                         Mem_Free(pixels);
6423                         Mem_Free(bumppixels);
6424                 }
6425                 else if (r_shadow_bumpscale_basetexture.value > 0)
6426                 {
6427                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6428                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6429                         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);
6430                         Mem_Free(pixels);
6431                 }
6432                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6433                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6434         }
6435
6436         // _luma is supported only for tenebrae compatibility
6437         // _glow is the preferred name
6438         mymiplevel = savemiplevel;
6439         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))))
6440         {
6441                 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);
6442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6443                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6444                 Mem_Free(pixels);pixels = NULL;
6445         }
6446
6447         mymiplevel = savemiplevel;
6448         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6449         {
6450                 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);
6451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6452                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6453                 Mem_Free(pixels);
6454                 pixels = NULL;
6455         }
6456
6457         mymiplevel = savemiplevel;
6458         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6459         {
6460                 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);
6461                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6462                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6463                 Mem_Free(pixels);
6464                 pixels = NULL;
6465         }
6466
6467         mymiplevel = savemiplevel;
6468         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6469         {
6470                 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);
6471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6472                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6473                 Mem_Free(pixels);
6474                 pixels = NULL;
6475         }
6476
6477         mymiplevel = savemiplevel;
6478         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6479         {
6480                 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);
6481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6482                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6483                 Mem_Free(pixels);
6484                 pixels = NULL;
6485         }
6486
6487         if (basepixels)
6488                 Mem_Free(basepixels);
6489
6490         return skinframe;
6491 }
6492
6493 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6494 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6495 {
6496         int i;
6497         unsigned char *temp1, *temp2;
6498         skinframe_t *skinframe;
6499
6500         if (cls.state == ca_dedicated)
6501                 return NULL;
6502
6503         // if already loaded just return it, otherwise make a new skinframe
6504         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6505         if (skinframe && skinframe->base)
6506                 return skinframe;
6507
6508         skinframe->stain = NULL;
6509         skinframe->merged = NULL;
6510         skinframe->base = NULL;
6511         skinframe->pants = NULL;
6512         skinframe->shirt = NULL;
6513         skinframe->nmap = NULL;
6514         skinframe->gloss = NULL;
6515         skinframe->glow = NULL;
6516         skinframe->fog = NULL;
6517         skinframe->reflect = NULL;
6518         skinframe->hasalpha = false;
6519
6520         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6521         if (!skindata)
6522                 return NULL;
6523
6524         if (developer_loading.integer)
6525                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6526
6527         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6528         {
6529                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6530                 temp2 = temp1 + width * height * 4;
6531                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6532                 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);
6533                 Mem_Free(temp1);
6534         }
6535         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6536         if (textureflags & TEXF_ALPHA)
6537         {
6538                 for (i = 3;i < width * height * 4;i += 4)
6539                 {
6540                         if (skindata[i] < 255)
6541                         {
6542                                 skinframe->hasalpha = true;
6543                                 break;
6544                         }
6545                 }
6546                 if (r_loadfog && skinframe->hasalpha)
6547                 {
6548                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6549                         memcpy(fogpixels, skindata, width * height * 4);
6550                         for (i = 0;i < width * height * 4;i += 4)
6551                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6552                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6553                         Mem_Free(fogpixels);
6554                 }
6555         }
6556
6557         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6558         //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]);
6559
6560         return skinframe;
6561 }
6562
6563 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6564 {
6565         int i;
6566         int featuresmask;
6567         skinframe_t *skinframe;
6568
6569         if (cls.state == ca_dedicated)
6570                 return NULL;
6571
6572         // if already loaded just return it, otherwise make a new skinframe
6573         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6574         if (skinframe && skinframe->base)
6575                 return skinframe;
6576
6577         skinframe->stain = NULL;
6578         skinframe->merged = NULL;
6579         skinframe->base = NULL;
6580         skinframe->pants = NULL;
6581         skinframe->shirt = NULL;
6582         skinframe->nmap = NULL;
6583         skinframe->gloss = NULL;
6584         skinframe->glow = NULL;
6585         skinframe->fog = NULL;
6586         skinframe->reflect = NULL;
6587         skinframe->hasalpha = false;
6588
6589         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6590         if (!skindata)
6591                 return NULL;
6592
6593         if (developer_loading.integer)
6594                 Con_Printf("loading quake skin \"%s\"\n", name);
6595
6596         // 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)
6597         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6598         memcpy(skinframe->qpixels, skindata, width*height);
6599         skinframe->qwidth = width;
6600         skinframe->qheight = height;
6601
6602         featuresmask = 0;
6603         for (i = 0;i < width * height;i++)
6604                 featuresmask |= palette_featureflags[skindata[i]];
6605
6606         skinframe->hasalpha = false;
6607         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6608         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6609         skinframe->qgeneratemerged = true;
6610         skinframe->qgeneratebase = skinframe->qhascolormapping;
6611         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6612
6613         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6614         //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]);
6615
6616         return skinframe;
6617 }
6618
6619 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6620 {
6621         int width;
6622         int height;
6623         unsigned char *skindata;
6624
6625         if (!skinframe->qpixels)
6626                 return;
6627
6628         if (!skinframe->qhascolormapping)
6629                 colormapped = false;
6630
6631         if (colormapped)
6632         {
6633                 if (!skinframe->qgeneratebase)
6634                         return;
6635         }
6636         else
6637         {
6638                 if (!skinframe->qgeneratemerged)
6639                         return;
6640         }
6641
6642         width = skinframe->qwidth;
6643         height = skinframe->qheight;
6644         skindata = skinframe->qpixels;
6645
6646         if (skinframe->qgeneratenmap)
6647         {
6648                 unsigned char *temp1, *temp2;
6649                 skinframe->qgeneratenmap = false;
6650                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6651                 temp2 = temp1 + width * height * 4;
6652                 // use either a custom palette or the quake palette
6653                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6654                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6655                 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);
6656                 Mem_Free(temp1);
6657         }
6658
6659         if (skinframe->qgenerateglow)
6660         {
6661                 skinframe->qgenerateglow = false;
6662                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6663         }
6664
6665         if (colormapped)
6666         {
6667                 skinframe->qgeneratebase = false;
6668                 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);
6669                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6670                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6671         }
6672         else
6673         {
6674                 skinframe->qgeneratemerged = false;
6675                 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);
6676         }
6677
6678         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6679         {
6680                 Mem_Free(skinframe->qpixels);
6681                 skinframe->qpixels = NULL;
6682         }
6683 }
6684
6685 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)
6686 {
6687         int i;
6688         skinframe_t *skinframe;
6689
6690         if (cls.state == ca_dedicated)
6691                 return NULL;
6692
6693         // if already loaded just return it, otherwise make a new skinframe
6694         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6695         if (skinframe && skinframe->base)
6696                 return skinframe;
6697
6698         skinframe->stain = NULL;
6699         skinframe->merged = NULL;
6700         skinframe->base = NULL;
6701         skinframe->pants = NULL;
6702         skinframe->shirt = NULL;
6703         skinframe->nmap = NULL;
6704         skinframe->gloss = NULL;
6705         skinframe->glow = NULL;
6706         skinframe->fog = NULL;
6707         skinframe->reflect = NULL;
6708         skinframe->hasalpha = false;
6709
6710         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6711         if (!skindata)
6712                 return NULL;
6713
6714         if (developer_loading.integer)
6715                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6716
6717         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6718         if (textureflags & TEXF_ALPHA)
6719         {
6720                 for (i = 0;i < width * height;i++)
6721                 {
6722                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6723                         {
6724                                 skinframe->hasalpha = true;
6725                                 break;
6726                         }
6727                 }
6728                 if (r_loadfog && skinframe->hasalpha)
6729                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6730         }
6731
6732         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6733         //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]);
6734
6735         return skinframe;
6736 }
6737
6738 skinframe_t *R_SkinFrame_LoadMissing(void)
6739 {
6740         skinframe_t *skinframe;
6741
6742         if (cls.state == ca_dedicated)
6743                 return NULL;
6744
6745         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6746         skinframe->stain = NULL;
6747         skinframe->merged = NULL;
6748         skinframe->base = NULL;
6749         skinframe->pants = NULL;
6750         skinframe->shirt = NULL;
6751         skinframe->nmap = NULL;
6752         skinframe->gloss = NULL;
6753         skinframe->glow = NULL;
6754         skinframe->fog = NULL;
6755         skinframe->reflect = NULL;
6756         skinframe->hasalpha = false;
6757
6758         skinframe->avgcolor[0] = rand() / RAND_MAX;
6759         skinframe->avgcolor[1] = rand() / RAND_MAX;
6760         skinframe->avgcolor[2] = rand() / RAND_MAX;
6761         skinframe->avgcolor[3] = 1;
6762
6763         return skinframe;
6764 }
6765
6766 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6767 typedef struct suffixinfo_s
6768 {
6769         const char *suffix;
6770         qboolean flipx, flipy, flipdiagonal;
6771 }
6772 suffixinfo_t;
6773 static suffixinfo_t suffix[3][6] =
6774 {
6775         {
6776                 {"px",   false, false, false},
6777                 {"nx",   false, false, false},
6778                 {"py",   false, false, false},
6779                 {"ny",   false, false, false},
6780                 {"pz",   false, false, false},
6781                 {"nz",   false, false, false}
6782         },
6783         {
6784                 {"posx", false, false, false},
6785                 {"negx", false, false, false},
6786                 {"posy", false, false, false},
6787                 {"negy", false, false, false},
6788                 {"posz", false, false, false},
6789                 {"negz", false, false, false}
6790         },
6791         {
6792                 {"rt",    true, false,  true},
6793                 {"lf",   false,  true,  true},
6794                 {"ft",    true,  true, false},
6795                 {"bk",   false, false, false},
6796                 {"up",    true, false,  true},
6797                 {"dn",    true, false,  true}
6798         }
6799 };
6800
6801 static int componentorder[4] = {0, 1, 2, 3};
6802
6803 rtexture_t *R_LoadCubemap(const char *basename)
6804 {
6805         int i, j, cubemapsize;
6806         unsigned char *cubemappixels, *image_buffer;
6807         rtexture_t *cubemaptexture;
6808         char name[256];
6809         // must start 0 so the first loadimagepixels has no requested width/height
6810         cubemapsize = 0;
6811         cubemappixels = NULL;
6812         cubemaptexture = NULL;
6813         // keep trying different suffix groups (posx, px, rt) until one loads
6814         for (j = 0;j < 3 && !cubemappixels;j++)
6815         {
6816                 // load the 6 images in the suffix group
6817                 for (i = 0;i < 6;i++)
6818                 {
6819                         // generate an image name based on the base and and suffix
6820                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6821                         // load it
6822                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6823                         {
6824                                 // an image loaded, make sure width and height are equal
6825                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6826                                 {
6827                                         // if this is the first image to load successfully, allocate the cubemap memory
6828                                         if (!cubemappixels && image_width >= 1)
6829                                         {
6830                                                 cubemapsize = image_width;
6831                                                 // note this clears to black, so unavailable sides are black
6832                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6833                                         }
6834                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6835                                         if (cubemappixels)
6836                                                 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);
6837                                 }
6838                                 else
6839                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6840                                 // free the image
6841                                 Mem_Free(image_buffer);
6842                         }
6843                 }
6844         }
6845         // if a cubemap loaded, upload it
6846         if (cubemappixels)
6847         {
6848                 if (developer_loading.integer)
6849                         Con_Printf("loading cubemap \"%s\"\n", basename);
6850
6851                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6852                 Mem_Free(cubemappixels);
6853         }
6854         else
6855         {
6856                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6857                 if (developer_loading.integer)
6858                 {
6859                         Con_Printf("(tried tried images ");
6860                         for (j = 0;j < 3;j++)
6861                                 for (i = 0;i < 6;i++)
6862                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6863                         Con_Print(" and was unable to find any of them).\n");
6864                 }
6865         }
6866         return cubemaptexture;
6867 }
6868
6869 rtexture_t *R_GetCubemap(const char *basename)
6870 {
6871         int i;
6872         for (i = 0;i < r_texture_numcubemaps;i++)
6873                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6874                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6875         if (i >= MAX_CUBEMAPS)
6876                 return r_texture_whitecube;
6877         r_texture_numcubemaps++;
6878         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6879         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6880         return r_texture_cubemaps[i].texture;
6881 }
6882
6883 void R_FreeCubemaps(void)
6884 {
6885         int i;
6886         for (i = 0;i < r_texture_numcubemaps;i++)
6887         {
6888                 if (developer_loading.integer)
6889                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6890                 if (r_texture_cubemaps[i].texture)
6891                         R_FreeTexture(r_texture_cubemaps[i].texture);
6892         }
6893         r_texture_numcubemaps = 0;
6894 }
6895
6896 void R_Main_FreeViewCache(void)
6897 {
6898         if (r_refdef.viewcache.entityvisible)
6899                 Mem_Free(r_refdef.viewcache.entityvisible);
6900         if (r_refdef.viewcache.world_pvsbits)
6901                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6902         if (r_refdef.viewcache.world_leafvisible)
6903                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6904         if (r_refdef.viewcache.world_surfacevisible)
6905                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6906         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6907 }
6908
6909 void R_Main_ResizeViewCache(void)
6910 {
6911         int numentities = r_refdef.scene.numentities;
6912         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6913         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6914         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6915         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6916         if (r_refdef.viewcache.maxentities < numentities)
6917         {
6918                 r_refdef.viewcache.maxentities = numentities;
6919                 if (r_refdef.viewcache.entityvisible)
6920                         Mem_Free(r_refdef.viewcache.entityvisible);
6921                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6922         }
6923         if (r_refdef.viewcache.world_numclusters != numclusters)
6924         {
6925                 r_refdef.viewcache.world_numclusters = numclusters;
6926                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6927                 if (r_refdef.viewcache.world_pvsbits)
6928                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6929                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6930         }
6931         if (r_refdef.viewcache.world_numleafs != numleafs)
6932         {
6933                 r_refdef.viewcache.world_numleafs = numleafs;
6934                 if (r_refdef.viewcache.world_leafvisible)
6935                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6936                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6937         }
6938         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6939         {
6940                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6941                 if (r_refdef.viewcache.world_surfacevisible)
6942                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6943                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6944         }
6945 }
6946
6947 extern rtexture_t *loadingscreentexture;
6948 void gl_main_start(void)
6949 {
6950         loadingscreentexture = NULL;
6951         r_texture_blanknormalmap = NULL;
6952         r_texture_white = NULL;
6953         r_texture_grey128 = NULL;
6954         r_texture_black = NULL;
6955         r_texture_whitecube = NULL;
6956         r_texture_normalizationcube = NULL;
6957         r_texture_fogattenuation = NULL;
6958         r_texture_fogheighttexture = NULL;
6959         r_texture_gammaramps = NULL;
6960         r_texture_numcubemaps = 0;
6961
6962         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6963         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6964
6965         switch(vid.renderpath)
6966         {
6967         case RENDERPATH_GL20:
6968         case RENDERPATH_CGGL:
6969         case RENDERPATH_D3D9:
6970         case RENDERPATH_D3D10:
6971         case RENDERPATH_D3D11:
6972                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6973                 Cvar_SetValueQuick(&gl_combine, 1);
6974                 Cvar_SetValueQuick(&r_glsl, 1);
6975                 r_loadnormalmap = true;
6976                 r_loadgloss = true;
6977                 r_loadfog = false;
6978                 break;
6979         case RENDERPATH_GL13:
6980                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6981                 Cvar_SetValueQuick(&gl_combine, 1);
6982                 Cvar_SetValueQuick(&r_glsl, 0);
6983                 r_loadnormalmap = false;
6984                 r_loadgloss = false;
6985                 r_loadfog = true;
6986                 break;
6987         case RENDERPATH_GL11:
6988                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6989                 Cvar_SetValueQuick(&gl_combine, 0);
6990                 Cvar_SetValueQuick(&r_glsl, 0);
6991                 r_loadnormalmap = false;
6992                 r_loadgloss = false;
6993                 r_loadfog = true;
6994                 break;
6995         }
6996
6997         R_AnimCache_Free();
6998         R_FrameData_Reset();
6999
7000         r_numqueries = 0;
7001         r_maxqueries = 0;
7002         memset(r_queries, 0, sizeof(r_queries));
7003
7004         r_qwskincache = NULL;
7005         r_qwskincache_size = 0;
7006
7007         // set up r_skinframe loading system for textures
7008         memset(&r_skinframe, 0, sizeof(r_skinframe));
7009         r_skinframe.loadsequence = 1;
7010         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7011
7012         r_main_texturepool = R_AllocTexturePool();
7013         R_BuildBlankTextures();
7014         R_BuildNoTexture();
7015         if (vid.support.arb_texture_cube_map)
7016         {
7017                 R_BuildWhiteCube();
7018                 R_BuildNormalizationCube();
7019         }
7020         r_texture_fogattenuation = NULL;
7021         r_texture_fogheighttexture = NULL;
7022         r_texture_gammaramps = NULL;
7023         //r_texture_fogintensity = NULL;
7024         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7025         memset(&r_waterstate, 0, sizeof(r_waterstate));
7026         r_glsl_permutation = NULL;
7027         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7028         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7029         glslshaderstring = NULL;
7030 #ifdef SUPPORTCG
7031         r_cg_permutation = NULL;
7032         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7033         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7034         cgshaderstring = NULL;
7035 #endif
7036 #ifdef SUPPORTD3D
7037         r_hlsl_permutation = NULL;
7038         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7039         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7040         hlslshaderstring = NULL;
7041 #endif
7042         memset(&r_svbsp, 0, sizeof (r_svbsp));
7043
7044         r_refdef.fogmasktable_density = 0;
7045 }
7046
7047 void gl_main_shutdown(void)
7048 {
7049         R_AnimCache_Free();
7050         R_FrameData_Reset();
7051
7052         R_Main_FreeViewCache();
7053
7054         switch(vid.renderpath)
7055         {
7056         case RENDERPATH_GL11:
7057         case RENDERPATH_GL13:
7058         case RENDERPATH_GL20:
7059         case RENDERPATH_CGGL:
7060                 if (r_maxqueries)
7061                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7062                 break;
7063         case RENDERPATH_D3D9:
7064                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7065                 break;
7066         case RENDERPATH_D3D10:
7067                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7068                 break;
7069         case RENDERPATH_D3D11:
7070                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7071                 break;
7072         }
7073
7074         r_numqueries = 0;
7075         r_maxqueries = 0;
7076         memset(r_queries, 0, sizeof(r_queries));
7077
7078         r_qwskincache = NULL;
7079         r_qwskincache_size = 0;
7080
7081         // clear out the r_skinframe state
7082         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7083         memset(&r_skinframe, 0, sizeof(r_skinframe));
7084
7085         if (r_svbsp.nodes)
7086                 Mem_Free(r_svbsp.nodes);
7087         memset(&r_svbsp, 0, sizeof (r_svbsp));
7088         R_FreeTexturePool(&r_main_texturepool);
7089         loadingscreentexture = NULL;
7090         r_texture_blanknormalmap = NULL;
7091         r_texture_white = NULL;
7092         r_texture_grey128 = NULL;
7093         r_texture_black = NULL;
7094         r_texture_whitecube = NULL;
7095         r_texture_normalizationcube = NULL;
7096         r_texture_fogattenuation = NULL;
7097         r_texture_fogheighttexture = NULL;
7098         r_texture_gammaramps = NULL;
7099         r_texture_numcubemaps = 0;
7100         //r_texture_fogintensity = NULL;
7101         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7102         memset(&r_waterstate, 0, sizeof(r_waterstate));
7103         R_GLSL_Restart_f();
7104 }
7105
7106 extern void CL_ParseEntityLump(char *entitystring);
7107 void gl_main_newmap(void)
7108 {
7109         // FIXME: move this code to client
7110         char *entities, entname[MAX_QPATH];
7111         if (r_qwskincache)
7112                 Mem_Free(r_qwskincache);
7113         r_qwskincache = NULL;
7114         r_qwskincache_size = 0;
7115         if (cl.worldmodel)
7116         {
7117                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7118                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7119                 {
7120                         CL_ParseEntityLump(entities);
7121                         Mem_Free(entities);
7122                         return;
7123                 }
7124                 if (cl.worldmodel->brush.entities)
7125                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7126         }
7127         R_Main_FreeViewCache();
7128
7129         R_FrameData_Reset();
7130 }
7131
7132 void GL_Main_Init(void)
7133 {
7134         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7135
7136         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7137         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7138         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7139         if (gamemode == GAME_NEHAHRA)
7140         {
7141                 Cvar_RegisterVariable (&gl_fogenable);
7142                 Cvar_RegisterVariable (&gl_fogdensity);
7143                 Cvar_RegisterVariable (&gl_fogred);
7144                 Cvar_RegisterVariable (&gl_foggreen);
7145                 Cvar_RegisterVariable (&gl_fogblue);
7146                 Cvar_RegisterVariable (&gl_fogstart);
7147                 Cvar_RegisterVariable (&gl_fogend);
7148                 Cvar_RegisterVariable (&gl_skyclip);
7149         }
7150         Cvar_RegisterVariable(&r_motionblur);
7151         Cvar_RegisterVariable(&r_motionblur_maxblur);
7152         Cvar_RegisterVariable(&r_motionblur_bmin);
7153         Cvar_RegisterVariable(&r_motionblur_vmin);
7154         Cvar_RegisterVariable(&r_motionblur_vmax);
7155         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7156         Cvar_RegisterVariable(&r_motionblur_randomize);
7157         Cvar_RegisterVariable(&r_damageblur);
7158         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7159         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7160         Cvar_RegisterVariable(&r_equalize_entities_by);
7161         Cvar_RegisterVariable(&r_equalize_entities_to);
7162         Cvar_RegisterVariable(&r_depthfirst);
7163         Cvar_RegisterVariable(&r_useinfinitefarclip);
7164         Cvar_RegisterVariable(&r_farclip_base);
7165         Cvar_RegisterVariable(&r_farclip_world);
7166         Cvar_RegisterVariable(&r_nearclip);
7167         Cvar_RegisterVariable(&r_showbboxes);
7168         Cvar_RegisterVariable(&r_showsurfaces);
7169         Cvar_RegisterVariable(&r_showtris);
7170         Cvar_RegisterVariable(&r_shownormals);
7171         Cvar_RegisterVariable(&r_showlighting);
7172         Cvar_RegisterVariable(&r_showshadowvolumes);
7173         Cvar_RegisterVariable(&r_showcollisionbrushes);
7174         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7175         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7176         Cvar_RegisterVariable(&r_showdisabledepthtest);
7177         Cvar_RegisterVariable(&r_drawportals);
7178         Cvar_RegisterVariable(&r_drawentities);
7179         Cvar_RegisterVariable(&r_draw2d);
7180         Cvar_RegisterVariable(&r_drawworld);
7181         Cvar_RegisterVariable(&r_cullentities_trace);
7182         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7183         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7184         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7185         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7186         Cvar_RegisterVariable(&r_drawviewmodel);
7187         Cvar_RegisterVariable(&r_drawexteriormodel);
7188         Cvar_RegisterVariable(&r_speeds);
7189         Cvar_RegisterVariable(&r_fullbrights);
7190         Cvar_RegisterVariable(&r_wateralpha);
7191         Cvar_RegisterVariable(&r_dynamic);
7192         Cvar_RegisterVariable(&r_fullbright);
7193         Cvar_RegisterVariable(&r_shadows);
7194         Cvar_RegisterVariable(&r_shadows_darken);
7195         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7196         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7197         Cvar_RegisterVariable(&r_shadows_throwdistance);
7198         Cvar_RegisterVariable(&r_shadows_throwdirection);
7199         Cvar_RegisterVariable(&r_shadows_focus);
7200         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7201         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7202         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7203         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7204         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7205         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7206         Cvar_RegisterVariable(&r_fog_exp2);
7207         Cvar_RegisterVariable(&r_drawfog);
7208         Cvar_RegisterVariable(&r_transparentdepthmasking);
7209         Cvar_RegisterVariable(&r_texture_dds_load);
7210         Cvar_RegisterVariable(&r_texture_dds_save);
7211         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7212         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7213         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7214         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7215         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7216         Cvar_RegisterVariable(&r_textureunits);
7217         Cvar_RegisterVariable(&gl_combine);
7218         Cvar_RegisterVariable(&r_glsl);
7219         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7220         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7221         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7222         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7223         Cvar_RegisterVariable(&r_glsl_postprocess);
7224         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7225         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7226         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7227         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7228         Cvar_RegisterVariable(&r_water);
7229         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7230         Cvar_RegisterVariable(&r_water_clippingplanebias);
7231         Cvar_RegisterVariable(&r_water_refractdistort);
7232         Cvar_RegisterVariable(&r_water_reflectdistort);
7233         Cvar_RegisterVariable(&r_lerpsprites);
7234         Cvar_RegisterVariable(&r_lerpmodels);
7235         Cvar_RegisterVariable(&r_lerplightstyles);
7236         Cvar_RegisterVariable(&r_waterscroll);
7237         Cvar_RegisterVariable(&r_bloom);
7238         Cvar_RegisterVariable(&r_bloom_colorscale);
7239         Cvar_RegisterVariable(&r_bloom_brighten);
7240         Cvar_RegisterVariable(&r_bloom_blur);
7241         Cvar_RegisterVariable(&r_bloom_resolution);
7242         Cvar_RegisterVariable(&r_bloom_colorexponent);
7243         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7244         Cvar_RegisterVariable(&r_hdr);
7245         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7246         Cvar_RegisterVariable(&r_hdr_glowintensity);
7247         Cvar_RegisterVariable(&r_hdr_range);
7248         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7249         Cvar_RegisterVariable(&developer_texturelogging);
7250         Cvar_RegisterVariable(&gl_lightmaps);
7251         Cvar_RegisterVariable(&r_test);
7252         Cvar_RegisterVariable(&r_glsl_saturation);
7253         Cvar_RegisterVariable(&r_framedatasize);
7254         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7255                 Cvar_SetValue("r_fullbrights", 0);
7256         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7257
7258         Cvar_RegisterVariable(&r_track_sprites);
7259         Cvar_RegisterVariable(&r_track_sprites_flags);
7260         Cvar_RegisterVariable(&r_track_sprites_scalew);
7261         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7262         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7263         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7264 }
7265
7266 extern void R_Textures_Init(void);
7267 extern void GL_Draw_Init(void);
7268 extern void GL_Main_Init(void);
7269 extern void R_Shadow_Init(void);
7270 extern void R_Sky_Init(void);
7271 extern void GL_Surf_Init(void);
7272 extern void R_Particles_Init(void);
7273 extern void R_Explosion_Init(void);
7274 extern void gl_backend_init(void);
7275 extern void Sbar_Init(void);
7276 extern void R_LightningBeams_Init(void);
7277 extern void Mod_RenderInit(void);
7278 extern void Font_Init(void);
7279
7280 void Render_Init(void)
7281 {
7282         gl_backend_init();
7283         R_Textures_Init();
7284         GL_Main_Init();
7285         Font_Init();
7286         GL_Draw_Init();
7287         R_Shadow_Init();
7288         R_Sky_Init();
7289         GL_Surf_Init();
7290         Sbar_Init();
7291         R_Particles_Init();
7292         R_Explosion_Init();
7293         R_LightningBeams_Init();
7294         Mod_RenderInit();
7295 }
7296
7297 /*
7298 ===============
7299 GL_Init
7300 ===============
7301 */
7302 extern char *ENGINE_EXTENSIONS;
7303 void GL_Init (void)
7304 {
7305         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7306         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7307         gl_version = (const char *)qglGetString(GL_VERSION);
7308         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7309
7310         if (!gl_extensions)
7311                 gl_extensions = "";
7312         if (!gl_platformextensions)
7313                 gl_platformextensions = "";
7314
7315         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7316         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7317         Con_Printf("GL_VERSION: %s\n", gl_version);
7318         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7319         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7320
7321         VID_CheckExtensions();
7322
7323         // LordHavoc: report supported extensions
7324         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7325
7326         // clear to black (loading plaque will be seen over this)
7327         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7328 }
7329
7330 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7331 {
7332         int i;
7333         mplane_t *p;
7334         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7335         {
7336                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7337                 if (i == 4)
7338                         continue;
7339                 p = r_refdef.view.frustum + i;
7340                 switch(p->signbits)
7341                 {
7342                 default:
7343                 case 0:
7344                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7345                                 return true;
7346                         break;
7347                 case 1:
7348                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7349                                 return true;
7350                         break;
7351                 case 2:
7352                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7353                                 return true;
7354                         break;
7355                 case 3:
7356                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7357                                 return true;
7358                         break;
7359                 case 4:
7360                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7361                                 return true;
7362                         break;
7363                 case 5:
7364                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7365                                 return true;
7366                         break;
7367                 case 6:
7368                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7369                                 return true;
7370                         break;
7371                 case 7:
7372                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7373                                 return true;
7374                         break;
7375                 }
7376         }
7377         return false;
7378 }
7379
7380 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7381 {
7382         int i;
7383         const mplane_t *p;
7384         for (i = 0;i < numplanes;i++)
7385         {
7386                 p = planes + i;
7387                 switch(p->signbits)
7388                 {
7389                 default:
7390                 case 0:
7391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7392                                 return true;
7393                         break;
7394                 case 1:
7395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7396                                 return true;
7397                         break;
7398                 case 2:
7399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7400                                 return true;
7401                         break;
7402                 case 3:
7403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7404                                 return true;
7405                         break;
7406                 case 4:
7407                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7408                                 return true;
7409                         break;
7410                 case 5:
7411                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7412                                 return true;
7413                         break;
7414                 case 6:
7415                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7416                                 return true;
7417                         break;
7418                 case 7:
7419                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7420                                 return true;
7421                         break;
7422                 }
7423         }
7424         return false;
7425 }
7426
7427 //==================================================================================
7428
7429 // LordHavoc: this stores temporary data used within the same frame
7430
7431 qboolean r_framedata_failed;
7432 static size_t r_framedata_size;
7433 static size_t r_framedata_current;
7434 static void *r_framedata_base;
7435
7436 void R_FrameData_Reset(void)
7437 {
7438         if (r_framedata_base)
7439                 Mem_Free(r_framedata_base);
7440         r_framedata_base = NULL;
7441         r_framedata_size = 0;
7442         r_framedata_current = 0;
7443         r_framedata_failed = false;
7444 }
7445
7446 void R_FrameData_NewFrame(void)
7447 {
7448         size_t wantedsize;
7449         if (r_framedata_failed)
7450                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7451         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7452         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7453         if (r_framedata_size != wantedsize)
7454         {
7455                 r_framedata_size = wantedsize;
7456                 if (r_framedata_base)
7457                         Mem_Free(r_framedata_base);
7458                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7459         }
7460         r_framedata_current = 0;
7461         r_framedata_failed = false;
7462 }
7463
7464 void *R_FrameData_Alloc(size_t size)
7465 {
7466         void *data;
7467
7468         // align to 16 byte boundary
7469         size = (size + 15) & ~15;
7470         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7471         r_framedata_current += size;
7472
7473         // check overflow
7474         if (r_framedata_current > r_framedata_size)
7475                 r_framedata_failed = true;
7476
7477         // return NULL on everything after a failure
7478         if (r_framedata_failed)
7479                 return NULL;
7480
7481         return data;
7482 }
7483
7484 void *R_FrameData_Store(size_t size, void *data)
7485 {
7486         void *d = R_FrameData_Alloc(size);
7487         if (d)
7488                 memcpy(d, data, size);
7489         return d;
7490 }
7491
7492 //==================================================================================
7493
7494 // LordHavoc: animcache originally written by Echon, rewritten since then
7495
7496 /**
7497  * Animation cache prevents re-generating mesh data for an animated model
7498  * multiple times in one frame for lighting, shadowing, reflections, etc.
7499  */
7500
7501 void R_AnimCache_Free(void)
7502 {
7503 }
7504
7505 void R_AnimCache_ClearCache(void)
7506 {
7507         int i;
7508         entity_render_t *ent;
7509
7510         for (i = 0;i < r_refdef.scene.numentities;i++)
7511         {
7512                 ent = r_refdef.scene.entities[i];
7513                 ent->animcache_vertex3f = NULL;
7514                 ent->animcache_normal3f = NULL;
7515                 ent->animcache_svector3f = NULL;
7516                 ent->animcache_tvector3f = NULL;
7517                 ent->animcache_vertexposition = NULL;
7518                 ent->animcache_vertexmesh = NULL;
7519                 ent->animcache_vertexpositionbuffer = NULL;
7520                 ent->animcache_vertexmeshbuffer = NULL;
7521         }
7522 }
7523
7524 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7525 {
7526         int i;
7527
7528         // identical memory layout, so no need to allocate...
7529         // this also provides the vertexposition structure to everything, e.g.
7530         // depth masked rendering currently uses it even if having separate
7531         // arrays
7532         // NOTE: get rid of this optimization if changing it to e.g. 4f
7533         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7534
7535         // TODO:
7536         // get rid of following uses of VERTEXPOSITION, change to the array:
7537         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7538         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7539         // R_DrawTextureSurfaceList_DepthOnly
7540         // R_Q1BSP_DrawShadowMap
7541
7542         switch(vid.renderpath)
7543         {
7544         case RENDERPATH_GL20:
7545         case RENDERPATH_CGGL:
7546                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7547                 if (gl_mesh_separatearrays.integer)
7548                         return;
7549                 break;
7550         case RENDERPATH_D3D9:
7551         case RENDERPATH_D3D10:
7552         case RENDERPATH_D3D11:
7553                 // always need the meshbuffers
7554                 break;
7555         case RENDERPATH_GL13:
7556         case RENDERPATH_GL11:
7557                 // never need the meshbuffers
7558                 return;
7559         }
7560
7561         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7562                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7563         /*
7564         if (!ent->animcache_vertexposition)
7565                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7566         */
7567         if (ent->animcache_vertexposition)
7568         {
7569                 /*
7570                 for (i = 0;i < numvertices;i++)
7571                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7572                 */
7573                 // TODO: upload vertex buffer?
7574         }
7575         if (ent->animcache_vertexmesh)
7576         {
7577                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7578                 for (i = 0;i < numvertices;i++)
7579                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7580                 if (ent->animcache_svector3f)
7581                         for (i = 0;i < numvertices;i++)
7582                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7583                 if (ent->animcache_tvector3f)
7584                         for (i = 0;i < numvertices;i++)
7585                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7586                 if (ent->animcache_normal3f)
7587                         for (i = 0;i < numvertices;i++)
7588                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7589                 // TODO: upload vertex buffer?
7590         }
7591 }
7592
7593 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7594 {
7595         dp_model_t *model = ent->model;
7596         int numvertices;
7597         // see if it's already cached this frame
7598         if (ent->animcache_vertex3f)
7599         {
7600                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7601                 if (wantnormals || wanttangents)
7602                 {
7603                         if (ent->animcache_normal3f)
7604                                 wantnormals = false;
7605                         if (ent->animcache_svector3f)
7606                                 wanttangents = false;
7607                         if (wantnormals || wanttangents)
7608                         {
7609                                 numvertices = model->surfmesh.num_vertices;
7610                                 if (wantnormals)
7611                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7612                                 if (wanttangents)
7613                                 {
7614                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7615                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7616                                 }
7617                                 if (!r_framedata_failed)
7618                                 {
7619                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7620                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7621                                 }
7622                         }
7623                 }
7624         }
7625         else
7626         {
7627                 // see if this ent is worth caching
7628                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7629                         return false;
7630                 // get some memory for this entity and generate mesh data
7631                 numvertices = model->surfmesh.num_vertices;
7632                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7633                 if (wantnormals)
7634                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7635                 if (wanttangents)
7636                 {
7637                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7638                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7639                 }
7640                 if (!r_framedata_failed)
7641                 {
7642                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7643                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7644                 }
7645         }
7646         return !r_framedata_failed;
7647 }
7648
7649 void R_AnimCache_CacheVisibleEntities(void)
7650 {
7651         int i;
7652         qboolean wantnormals = true;
7653         qboolean wanttangents = !r_showsurfaces.integer;
7654
7655         switch(vid.renderpath)
7656         {
7657         case RENDERPATH_GL20:
7658         case RENDERPATH_CGGL:
7659         case RENDERPATH_D3D9:
7660         case RENDERPATH_D3D10:
7661         case RENDERPATH_D3D11:
7662                 break;
7663         case RENDERPATH_GL13:
7664         case RENDERPATH_GL11:
7665                 wanttangents = false;
7666                 break;
7667         }
7668
7669         if (r_shownormals.integer)
7670                 wanttangents = wantnormals = true;
7671
7672         // TODO: thread this
7673         // NOTE: R_PrepareRTLights() also caches entities
7674
7675         for (i = 0;i < r_refdef.scene.numentities;i++)
7676                 if (r_refdef.viewcache.entityvisible[i])
7677                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7678 }
7679
7680 //==================================================================================
7681
7682 static void R_View_UpdateEntityLighting (void)
7683 {
7684         int i;
7685         entity_render_t *ent;
7686         vec3_t tempdiffusenormal, avg;
7687         vec_t f, fa, fd, fdd;
7688         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7689
7690         for (i = 0;i < r_refdef.scene.numentities;i++)
7691         {
7692                 ent = r_refdef.scene.entities[i];
7693
7694                 // skip unseen models
7695                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7696                         continue;
7697
7698                 // skip bsp models
7699                 if (ent->model && ent->model->brush.num_leafs)
7700                 {
7701                         // TODO: use modellight for r_ambient settings on world?
7702                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7703                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7704                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7705                         continue;
7706                 }
7707
7708                 // fetch the lighting from the worldmodel data
7709                 VectorClear(ent->modellight_ambient);
7710                 VectorClear(ent->modellight_diffuse);
7711                 VectorClear(tempdiffusenormal);
7712                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7713                 {
7714                         vec3_t org;
7715                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7716                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7717                         if(ent->flags & RENDER_EQUALIZE)
7718                         {
7719                                 // first fix up ambient lighting...
7720                                 if(r_equalize_entities_minambient.value > 0)
7721                                 {
7722                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7723                                         if(fd > 0)
7724                                         {
7725                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7726                                                 if(fa < r_equalize_entities_minambient.value * fd)
7727                                                 {
7728                                                         // solve:
7729                                                         //   fa'/fd' = minambient
7730                                                         //   fa'+0.25*fd' = fa+0.25*fd
7731                                                         //   ...
7732                                                         //   fa' = fd' * minambient
7733                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7734                                                         //   ...
7735                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7736                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7737                                                         //   ...
7738                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7739                                                         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
7740                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7741                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7742                                                 }
7743                                         }
7744                                 }
7745
7746                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7747                                 {
7748                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7749                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7750                                         if(f > 0)
7751                                         {
7752                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7753                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7754                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7755                                         }
7756                                 }
7757                         }
7758                 }
7759                 else // highly rare
7760                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7761
7762                 // move the light direction into modelspace coordinates for lighting code
7763                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7764                 if(VectorLength2(ent->modellight_lightdir) == 0)
7765                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7766                 VectorNormalize(ent->modellight_lightdir);
7767         }
7768 }
7769
7770 #define MAX_LINEOFSIGHTTRACES 64
7771
7772 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7773 {
7774         int i;
7775         vec3_t boxmins, boxmaxs;
7776         vec3_t start;
7777         vec3_t end;
7778         dp_model_t *model = r_refdef.scene.worldmodel;
7779
7780         if (!model || !model->brush.TraceLineOfSight)
7781                 return true;
7782
7783         // expand the box a little
7784         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7785         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7786         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7787         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7788         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7789         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7790
7791         // return true if eye is inside enlarged box
7792         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7793                 return true;
7794
7795         // try center
7796         VectorCopy(eye, start);
7797         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7798         if (model->brush.TraceLineOfSight(model, start, end))
7799                 return true;
7800
7801         // try various random positions
7802         for (i = 0;i < numsamples;i++)
7803         {
7804                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7805                 if (model->brush.TraceLineOfSight(model, start, end))
7806                         return true;
7807         }
7808
7809         return false;
7810 }
7811
7812
7813 static void R_View_UpdateEntityVisible (void)
7814 {
7815         int i;
7816         int renderimask;
7817         int samples;
7818         entity_render_t *ent;
7819
7820         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7821                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7822                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7823                 :                                                          RENDER_EXTERIORMODEL;
7824         if (!r_drawviewmodel.integer)
7825                 renderimask |= RENDER_VIEWMODEL;
7826         if (!r_drawexteriormodel.integer)
7827                 renderimask |= RENDER_EXTERIORMODEL;
7828         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7829         {
7830                 // worldmodel can check visibility
7831                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7832                 for (i = 0;i < r_refdef.scene.numentities;i++)
7833                 {
7834                         ent = r_refdef.scene.entities[i];
7835                         if (!(ent->flags & renderimask))
7836                         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)))
7837                         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))
7838                                 r_refdef.viewcache.entityvisible[i] = true;
7839                 }
7840                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7841                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7842                 {
7843                         for (i = 0;i < r_refdef.scene.numentities;i++)
7844                         {
7845                                 ent = r_refdef.scene.entities[i];
7846                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7847                                 {
7848                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7849                                         if (samples < 0)
7850                                                 continue; // temp entities do pvs only
7851                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7852                                                 ent->last_trace_visibility = realtime;
7853                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7854                                                 r_refdef.viewcache.entityvisible[i] = 0;
7855                                 }
7856                         }
7857                 }
7858         }
7859         else
7860         {
7861                 // no worldmodel or it can't check visibility
7862                 for (i = 0;i < r_refdef.scene.numentities;i++)
7863                 {
7864                         ent = r_refdef.scene.entities[i];
7865                         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));
7866                 }
7867         }
7868 }
7869
7870 /// only used if skyrendermasked, and normally returns false
7871 int R_DrawBrushModelsSky (void)
7872 {
7873         int i, sky;
7874         entity_render_t *ent;
7875
7876         sky = false;
7877         for (i = 0;i < r_refdef.scene.numentities;i++)
7878         {
7879                 if (!r_refdef.viewcache.entityvisible[i])
7880                         continue;
7881                 ent = r_refdef.scene.entities[i];
7882                 if (!ent->model || !ent->model->DrawSky)
7883                         continue;
7884                 ent->model->DrawSky(ent);
7885                 sky = true;
7886         }
7887         return sky;
7888 }
7889
7890 static void R_DrawNoModel(entity_render_t *ent);
7891 static void R_DrawModels(void)
7892 {
7893         int i;
7894         entity_render_t *ent;
7895
7896         for (i = 0;i < r_refdef.scene.numentities;i++)
7897         {
7898                 if (!r_refdef.viewcache.entityvisible[i])
7899                         continue;
7900                 ent = r_refdef.scene.entities[i];
7901                 r_refdef.stats.entities++;
7902                 if (ent->model && ent->model->Draw != NULL)
7903                         ent->model->Draw(ent);
7904                 else
7905                         R_DrawNoModel(ent);
7906         }
7907 }
7908
7909 static void R_DrawModelsDepth(void)
7910 {
7911         int i;
7912         entity_render_t *ent;
7913
7914         for (i = 0;i < r_refdef.scene.numentities;i++)
7915         {
7916                 if (!r_refdef.viewcache.entityvisible[i])
7917                         continue;
7918                 ent = r_refdef.scene.entities[i];
7919                 if (ent->model && ent->model->DrawDepth != NULL)
7920                         ent->model->DrawDepth(ent);
7921         }
7922 }
7923
7924 static void R_DrawModelsDebug(void)
7925 {
7926         int i;
7927         entity_render_t *ent;
7928
7929         for (i = 0;i < r_refdef.scene.numentities;i++)
7930         {
7931                 if (!r_refdef.viewcache.entityvisible[i])
7932                         continue;
7933                 ent = r_refdef.scene.entities[i];
7934                 if (ent->model && ent->model->DrawDebug != NULL)
7935                         ent->model->DrawDebug(ent);
7936         }
7937 }
7938
7939 static void R_DrawModelsAddWaterPlanes(void)
7940 {
7941         int i;
7942         entity_render_t *ent;
7943
7944         for (i = 0;i < r_refdef.scene.numentities;i++)
7945         {
7946                 if (!r_refdef.viewcache.entityvisible[i])
7947                         continue;
7948                 ent = r_refdef.scene.entities[i];
7949                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7950                         ent->model->DrawAddWaterPlanes(ent);
7951         }
7952 }
7953
7954 static void R_View_SetFrustum(void)
7955 {
7956         int i;
7957         double slopex, slopey;
7958         vec3_t forward, left, up, origin;
7959
7960         // we can't trust r_refdef.view.forward and friends in reflected scenes
7961         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7962
7963 #if 0
7964         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7965         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7966         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7967         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7968         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7969         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7970         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7971         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7972         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7973         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7974         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7975         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7976 #endif
7977
7978 #if 0
7979         zNear = r_refdef.nearclip;
7980         nudge = 1.0 - 1.0 / (1<<23);
7981         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7982         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7983         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7984         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7985         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7986         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7987         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7988         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7989 #endif
7990
7991
7992
7993 #if 0
7994         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7995         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7996         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7997         r_refdef.view.frustum[0].dist = m[15] - m[12];
7998
7999         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8000         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8001         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8002         r_refdef.view.frustum[1].dist = m[15] + m[12];
8003
8004         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8005         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8006         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8007         r_refdef.view.frustum[2].dist = m[15] - m[13];
8008
8009         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8010         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8011         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8012         r_refdef.view.frustum[3].dist = m[15] + m[13];
8013
8014         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8015         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8016         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8017         r_refdef.view.frustum[4].dist = m[15] - m[14];
8018
8019         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8020         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8021         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8022         r_refdef.view.frustum[5].dist = m[15] + m[14];
8023 #endif
8024
8025         if (r_refdef.view.useperspective)
8026         {
8027                 slopex = 1.0 / r_refdef.view.frustum_x;
8028                 slopey = 1.0 / r_refdef.view.frustum_y;
8029                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8030                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8031                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8032                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8033                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8034
8035                 // Leaving those out was a mistake, those were in the old code, and they
8036                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8037                 // I couldn't reproduce it after adding those normalizations. --blub
8038                 VectorNormalize(r_refdef.view.frustum[0].normal);
8039                 VectorNormalize(r_refdef.view.frustum[1].normal);
8040                 VectorNormalize(r_refdef.view.frustum[2].normal);
8041                 VectorNormalize(r_refdef.view.frustum[3].normal);
8042
8043                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8044                 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]);
8045                 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]);
8046                 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]);
8047                 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]);
8048
8049                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8050                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8051                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8052                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8053                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8054         }
8055         else
8056         {
8057                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8058                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8059                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8060                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8061                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8062                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8063                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8064                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8065                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8066                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8067         }
8068         r_refdef.view.numfrustumplanes = 5;
8069
8070         if (r_refdef.view.useclipplane)
8071         {
8072                 r_refdef.view.numfrustumplanes = 6;
8073                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8074         }
8075
8076         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8077                 PlaneClassify(r_refdef.view.frustum + i);
8078
8079         // LordHavoc: note to all quake engine coders, Quake had a special case
8080         // for 90 degrees which assumed a square view (wrong), so I removed it,
8081         // Quake2 has it disabled as well.
8082
8083         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8084         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8085         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8086         //PlaneClassify(&frustum[0]);
8087
8088         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8089         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8090         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8091         //PlaneClassify(&frustum[1]);
8092
8093         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8094         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8095         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8096         //PlaneClassify(&frustum[2]);
8097
8098         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8099         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8100         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8101         //PlaneClassify(&frustum[3]);
8102
8103         // nearclip plane
8104         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8105         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8106         //PlaneClassify(&frustum[4]);
8107 }
8108
8109 void R_View_Update(void)
8110 {
8111         R_Main_ResizeViewCache();
8112         R_View_SetFrustum();
8113         R_View_WorldVisibility(r_refdef.view.useclipplane);
8114         R_View_UpdateEntityVisible();
8115         R_View_UpdateEntityLighting();
8116 }
8117
8118 void R_SetupView(qboolean allowwaterclippingplane)
8119 {
8120         const float *customclipplane = NULL;
8121         float plane[4];
8122         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8123         {
8124                 // LordHavoc: couldn't figure out how to make this approach the
8125                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8126                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8127                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8128                         dist = r_refdef.view.clipplane.dist;
8129                 plane[0] = r_refdef.view.clipplane.normal[0];
8130                 plane[1] = r_refdef.view.clipplane.normal[1];
8131                 plane[2] = r_refdef.view.clipplane.normal[2];
8132                 plane[3] = dist;
8133                 customclipplane = plane;
8134         }
8135
8136         if (!r_refdef.view.useperspective)
8137                 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);
8138         else if (vid.stencil && r_useinfinitefarclip.integer)
8139                 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);
8140         else
8141                 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);
8142         R_SetViewport(&r_refdef.view.viewport);
8143 }
8144
8145 void R_EntityMatrix(const matrix4x4_t *matrix)
8146 {
8147         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8148         {
8149                 gl_modelmatrixchanged = false;
8150                 gl_modelmatrix = *matrix;
8151                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8152                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8153                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8154                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8155                 CHECKGLERROR
8156                 switch(vid.renderpath)
8157                 {
8158                 case RENDERPATH_D3D9:
8159 #ifdef SUPPORTD3D
8160                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8161                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8162 #endif
8163                         break;
8164                 case RENDERPATH_D3D10:
8165                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8166                         break;
8167                 case RENDERPATH_D3D11:
8168                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8169                         break;
8170                 case RENDERPATH_GL20:
8171                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8172                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8173                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8174                         break;
8175                 case RENDERPATH_CGGL:
8176 #ifdef SUPPORTCG
8177                         CHECKCGERROR
8178                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8179                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8180                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8181 #endif
8182                         break;
8183                 case RENDERPATH_GL13:
8184                 case RENDERPATH_GL11:
8185                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8186                         break;
8187                 }
8188         }
8189 }
8190
8191 void R_ResetViewRendering2D(void)
8192 {
8193         r_viewport_t viewport;
8194         DrawQ_Finish();
8195
8196         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8197         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);
8198         R_SetViewport(&viewport);
8199         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8200         GL_Color(1, 1, 1, 1);
8201         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8202         GL_BlendFunc(GL_ONE, GL_ZERO);
8203         GL_AlphaTest(false);
8204         GL_ScissorTest(false);
8205         GL_DepthMask(false);
8206         GL_DepthRange(0, 1);
8207         GL_DepthTest(false);
8208         GL_DepthFunc(GL_LEQUAL);
8209         R_EntityMatrix(&identitymatrix);
8210         R_Mesh_ResetTextureState();
8211         GL_PolygonOffset(0, 0);
8212         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8213         switch(vid.renderpath)
8214         {
8215         case RENDERPATH_GL11:
8216         case RENDERPATH_GL13:
8217         case RENDERPATH_GL20:
8218         case RENDERPATH_CGGL:
8219                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8220                 break;
8221         case RENDERPATH_D3D9:
8222         case RENDERPATH_D3D10:
8223         case RENDERPATH_D3D11:
8224                 break;
8225         }
8226         GL_CullFace(GL_NONE);
8227 }
8228
8229 void R_ResetViewRendering3D(void)
8230 {
8231         DrawQ_Finish();
8232
8233         R_SetupView(true);
8234         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8235         GL_Color(1, 1, 1, 1);
8236         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8237         GL_BlendFunc(GL_ONE, GL_ZERO);
8238         GL_AlphaTest(false);
8239         GL_ScissorTest(true);
8240         GL_DepthMask(true);
8241         GL_DepthRange(0, 1);
8242         GL_DepthTest(true);
8243         GL_DepthFunc(GL_LEQUAL);
8244         R_EntityMatrix(&identitymatrix);
8245         R_Mesh_ResetTextureState();
8246         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8247         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8248         switch(vid.renderpath)
8249         {
8250         case RENDERPATH_GL11:
8251         case RENDERPATH_GL13:
8252         case RENDERPATH_GL20:
8253         case RENDERPATH_CGGL:
8254                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8255                 break;
8256         case RENDERPATH_D3D9:
8257         case RENDERPATH_D3D10:
8258         case RENDERPATH_D3D11:
8259                 break;
8260         }
8261         GL_CullFace(r_refdef.view.cullface_back);
8262 }
8263
8264 /*
8265 ================
8266 R_RenderView_UpdateViewVectors
8267 ================
8268 */
8269 static void R_RenderView_UpdateViewVectors(void)
8270 {
8271         // break apart the view matrix into vectors for various purposes
8272         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8273         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8274         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8275         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8276         // make an inverted copy of the view matrix for tracking sprites
8277         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8278 }
8279
8280 void R_RenderScene(void);
8281 void R_RenderWaterPlanes(void);
8282
8283 static void R_Water_StartFrame(void)
8284 {
8285         int i;
8286         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8287         r_waterstate_waterplane_t *p;
8288
8289         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8290                 return;
8291
8292         switch(vid.renderpath)
8293         {
8294         case RENDERPATH_GL20:
8295         case RENDERPATH_CGGL:
8296         case RENDERPATH_D3D9:
8297         case RENDERPATH_D3D10:
8298         case RENDERPATH_D3D11:
8299                 break;
8300         case RENDERPATH_GL13:
8301         case RENDERPATH_GL11:
8302                 return;
8303         }
8304
8305         // set waterwidth and waterheight to the water resolution that will be
8306         // used (often less than the screen resolution for faster rendering)
8307         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8308         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8309
8310         // calculate desired texture sizes
8311         // can't use water if the card does not support the texture size
8312         if (!r_water.integer || r_showsurfaces.integer)
8313                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8314         else if (vid.support.arb_texture_non_power_of_two)
8315         {
8316                 texturewidth = waterwidth;
8317                 textureheight = waterheight;
8318                 camerawidth = waterwidth;
8319                 cameraheight = waterheight;
8320         }
8321         else
8322         {
8323                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8324                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8325                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8326                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8327         }
8328
8329         // allocate textures as needed
8330         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8331         {
8332                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8333                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8334                 {
8335                         if (p->texture_refraction)
8336                                 R_FreeTexture(p->texture_refraction);
8337                         p->texture_refraction = NULL;
8338                         if (p->texture_reflection)
8339                                 R_FreeTexture(p->texture_reflection);
8340                         p->texture_reflection = NULL;
8341                         if (p->texture_camera)
8342                                 R_FreeTexture(p->texture_camera);
8343                         p->texture_camera = NULL;
8344                 }
8345                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8346                 r_waterstate.texturewidth = texturewidth;
8347                 r_waterstate.textureheight = textureheight;
8348                 r_waterstate.camerawidth = camerawidth;
8349                 r_waterstate.cameraheight = cameraheight;
8350         }
8351
8352         if (r_waterstate.texturewidth)
8353         {
8354                 r_waterstate.enabled = true;
8355
8356                 // when doing a reduced render (HDR) we want to use a smaller area
8357                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8358                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8359
8360                 // set up variables that will be used in shader setup
8361                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8362                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8363                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8364                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8365         }
8366
8367         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8368         r_waterstate.numwaterplanes = 0;
8369 }
8370
8371 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8372 {
8373         int triangleindex, planeindex;
8374         const int *e;
8375         vec3_t vert[3];
8376         vec3_t normal;
8377         vec3_t center;
8378         mplane_t plane;
8379         int cam_ent;
8380         r_waterstate_waterplane_t *p;
8381         texture_t *t = R_GetCurrentTexture(surface->texture);
8382         cam_ent = t->camera_entity;
8383         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8384                 cam_ent = 0;
8385
8386         // just use the first triangle with a valid normal for any decisions
8387         VectorClear(normal);
8388         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8389         {
8390                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8391                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8392                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8393                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8394                 if (VectorLength2(normal) >= 0.001)
8395                         break;
8396         }
8397
8398         VectorCopy(normal, plane.normal);
8399         VectorNormalize(plane.normal);
8400         plane.dist = DotProduct(vert[0], plane.normal);
8401         PlaneClassify(&plane);
8402         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8403         {
8404                 // skip backfaces (except if nocullface is set)
8405                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8406                         return;
8407                 VectorNegate(plane.normal, plane.normal);
8408                 plane.dist *= -1;
8409                 PlaneClassify(&plane);
8410         }
8411
8412
8413         // find a matching plane if there is one
8414         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8415                 if(p->camera_entity == t->camera_entity)
8416                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8417                                 break;
8418         if (planeindex >= r_waterstate.maxwaterplanes)
8419                 return; // nothing we can do, out of planes
8420
8421         // if this triangle does not fit any known plane rendered this frame, add one
8422         if (planeindex >= r_waterstate.numwaterplanes)
8423         {
8424                 // store the new plane
8425                 r_waterstate.numwaterplanes++;
8426                 p->plane = plane;
8427                 // clear materialflags and pvs
8428                 p->materialflags = 0;
8429                 p->pvsvalid = false;
8430                 p->camera_entity = t->camera_entity;
8431         }
8432         // merge this surface's materialflags into the waterplane
8433         p->materialflags |= t->currentmaterialflags;
8434         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8435         {
8436                 // merge this surface's PVS into the waterplane
8437                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8438                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8439                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8440                 {
8441                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8442                         p->pvsvalid = true;
8443                 }
8444         }
8445 }
8446
8447 static void R_Water_ProcessPlanes(void)
8448 {
8449         r_refdef_view_t originalview;
8450         r_refdef_view_t myview;
8451         int planeindex;
8452         r_waterstate_waterplane_t *p;
8453         vec3_t visorigin;
8454
8455         originalview = r_refdef.view;
8456
8457         // make sure enough textures are allocated
8458         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8459         {
8460                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8461                 {
8462                         if (!p->texture_refraction)
8463                                 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);
8464                         if (!p->texture_refraction)
8465                                 goto error;
8466                 }
8467                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8468                 {
8469                         if (!p->texture_camera)
8470                                 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);
8471                         if (!p->texture_camera)
8472                                 goto error;
8473                 }
8474
8475                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8476                 {
8477                         if (!p->texture_reflection)
8478                                 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);
8479                         if (!p->texture_reflection)
8480                                 goto error;
8481                 }
8482         }
8483
8484         // render views
8485         r_refdef.view = originalview;
8486         r_refdef.view.showdebug = false;
8487         r_refdef.view.width = r_waterstate.waterwidth;
8488         r_refdef.view.height = r_waterstate.waterheight;
8489         r_refdef.view.useclipplane = true;
8490         myview = r_refdef.view;
8491         r_waterstate.renderingscene = true;
8492         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8493         {
8494                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8495                 {
8496                         r_refdef.view = myview;
8497                         // render reflected scene and copy into texture
8498                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8499                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8500                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8501                         r_refdef.view.clipplane = p->plane;
8502                         // reverse the cullface settings for this render
8503                         r_refdef.view.cullface_front = GL_FRONT;
8504                         r_refdef.view.cullface_back = GL_BACK;
8505                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8506                         {
8507                                 r_refdef.view.usecustompvs = true;
8508                                 if (p->pvsvalid)
8509                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8510                                 else
8511                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8512                         }
8513
8514                         R_ResetViewRendering3D();
8515                         R_ClearScreen(r_refdef.fogenabled);
8516                         R_View_Update();
8517                         R_RenderScene();
8518
8519                         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);
8520                 }
8521
8522                 // render the normal view scene and copy into texture
8523                 // (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)
8524                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8525                 {
8526                         r_waterstate.renderingrefraction = true;
8527                         r_refdef.view = myview;
8528
8529                         r_refdef.view.clipplane = p->plane;
8530                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8531                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8532
8533                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8534                         {
8535                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8536                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8537                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8538                                 R_RenderView_UpdateViewVectors();
8539                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8540                                 {
8541                                         r_refdef.view.usecustompvs = true;
8542                                         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);
8543                                 }
8544                         }
8545
8546                         PlaneClassify(&r_refdef.view.clipplane);
8547
8548                         R_ResetViewRendering3D();
8549                         R_ClearScreen(r_refdef.fogenabled);
8550                         R_View_Update();
8551                         R_RenderScene();
8552
8553                         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);
8554                         r_waterstate.renderingrefraction = false;
8555                 }
8556                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8557                 {
8558                         r_refdef.view = myview;
8559
8560                         r_refdef.view.clipplane = p->plane;
8561                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8562                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8563
8564                         r_refdef.view.width = r_waterstate.camerawidth;
8565                         r_refdef.view.height = r_waterstate.cameraheight;
8566                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8567                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8568
8569                         if(p->camera_entity)
8570                         {
8571                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8572                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8573                         }
8574
8575                         // reverse the cullface settings for this render
8576                         r_refdef.view.cullface_front = GL_FRONT;
8577                         r_refdef.view.cullface_back = GL_BACK;
8578                         // also reverse the view matrix
8579                         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
8580                         R_RenderView_UpdateViewVectors();
8581                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8582                         {
8583                                 r_refdef.view.usecustompvs = true;
8584                                 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);
8585                         }
8586                         
8587                         // camera needs no clipplane
8588                         r_refdef.view.useclipplane = false;
8589
8590                         PlaneClassify(&r_refdef.view.clipplane);
8591
8592                         R_ResetViewRendering3D();
8593                         R_ClearScreen(r_refdef.fogenabled);
8594                         R_View_Update();
8595                         R_RenderScene();
8596
8597                         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);
8598                         r_waterstate.renderingrefraction = false;
8599                 }
8600
8601         }
8602         r_waterstate.renderingscene = false;
8603         r_refdef.view = originalview;
8604         R_ResetViewRendering3D();
8605         R_ClearScreen(r_refdef.fogenabled);
8606         R_View_Update();
8607         return;
8608 error:
8609         r_refdef.view = originalview;
8610         r_waterstate.renderingscene = false;
8611         Cvar_SetValueQuick(&r_water, 0);
8612         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8613         return;
8614 }
8615
8616 void R_Bloom_StartFrame(void)
8617 {
8618         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8619
8620         switch(vid.renderpath)
8621         {
8622         case RENDERPATH_GL20:
8623         case RENDERPATH_CGGL:
8624         case RENDERPATH_D3D9:
8625         case RENDERPATH_D3D10:
8626         case RENDERPATH_D3D11:
8627                 break;
8628         case RENDERPATH_GL13:
8629         case RENDERPATH_GL11:
8630                 return;
8631         }
8632
8633         // set bloomwidth and bloomheight to the bloom resolution that will be
8634         // used (often less than the screen resolution for faster rendering)
8635         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8636         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8637         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8638         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8639         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8640
8641         // calculate desired texture sizes
8642         if (vid.support.arb_texture_non_power_of_two)
8643         {
8644                 screentexturewidth = r_refdef.view.width;
8645                 screentextureheight = r_refdef.view.height;
8646                 bloomtexturewidth = r_bloomstate.bloomwidth;
8647                 bloomtextureheight = r_bloomstate.bloomheight;
8648         }
8649         else
8650         {
8651                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8652                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8653                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8654                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8655         }
8656
8657         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))
8658         {
8659                 Cvar_SetValueQuick(&r_hdr, 0);
8660                 Cvar_SetValueQuick(&r_bloom, 0);
8661                 Cvar_SetValueQuick(&r_motionblur, 0);
8662                 Cvar_SetValueQuick(&r_damageblur, 0);
8663         }
8664
8665         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)))
8666                 screentexturewidth = screentextureheight = 0;
8667         if (!r_hdr.integer && !r_bloom.integer)
8668                 bloomtexturewidth = bloomtextureheight = 0;
8669
8670         // allocate textures as needed
8671         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8672         {
8673                 if (r_bloomstate.texture_screen)
8674                         R_FreeTexture(r_bloomstate.texture_screen);
8675                 r_bloomstate.texture_screen = NULL;
8676                 r_bloomstate.screentexturewidth = screentexturewidth;
8677                 r_bloomstate.screentextureheight = screentextureheight;
8678                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8679                         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);
8680         }
8681         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8682         {
8683                 if (r_bloomstate.texture_bloom)
8684                         R_FreeTexture(r_bloomstate.texture_bloom);
8685                 r_bloomstate.texture_bloom = NULL;
8686                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8687                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8688                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8689                         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);
8690         }
8691
8692         // when doing a reduced render (HDR) we want to use a smaller area
8693         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8694         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8695         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8696         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8697         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8698
8699         // set up a texcoord array for the full resolution screen image
8700         // (we have to keep this around to copy back during final render)
8701         r_bloomstate.screentexcoord2f[0] = 0;
8702         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8703         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8704         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8705         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8706         r_bloomstate.screentexcoord2f[5] = 0;
8707         r_bloomstate.screentexcoord2f[6] = 0;
8708         r_bloomstate.screentexcoord2f[7] = 0;
8709
8710         // set up a texcoord array for the reduced resolution bloom image
8711         // (which will be additive blended over the screen image)
8712         r_bloomstate.bloomtexcoord2f[0] = 0;
8713         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8714         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8715         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8716         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8717         r_bloomstate.bloomtexcoord2f[5] = 0;
8718         r_bloomstate.bloomtexcoord2f[6] = 0;
8719         r_bloomstate.bloomtexcoord2f[7] = 0;
8720
8721         switch(vid.renderpath)
8722         {
8723         case RENDERPATH_GL11:
8724         case RENDERPATH_GL13:
8725         case RENDERPATH_GL20:
8726         case RENDERPATH_CGGL:
8727                 break;
8728         case RENDERPATH_D3D9:
8729         case RENDERPATH_D3D10:
8730         case RENDERPATH_D3D11:
8731                 {
8732                         int i;
8733                         for (i = 0;i < 4;i++)
8734                         {
8735                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8736                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8737                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8738                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8739                         }
8740                 }
8741                 break;
8742         }
8743
8744         if (r_hdr.integer || r_bloom.integer)
8745         {
8746                 r_bloomstate.enabled = true;
8747                 r_bloomstate.hdr = r_hdr.integer != 0;
8748         }
8749
8750         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);
8751 }
8752
8753 void R_Bloom_CopyBloomTexture(float colorscale)
8754 {
8755         r_refdef.stats.bloom++;
8756
8757         // scale down screen texture to the bloom texture size
8758         CHECKGLERROR
8759         R_SetViewport(&r_bloomstate.viewport);
8760         GL_BlendFunc(GL_ONE, GL_ZERO);
8761         GL_Color(colorscale, colorscale, colorscale, 1);
8762         // 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...
8763         switch(vid.renderpath)
8764         {
8765         case RENDERPATH_GL11:
8766         case RENDERPATH_GL13:
8767         case RENDERPATH_GL20:
8768         case RENDERPATH_CGGL:
8769                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8770                 break;
8771         case RENDERPATH_D3D9:
8772         case RENDERPATH_D3D10:
8773         case RENDERPATH_D3D11:
8774                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8775                 break;
8776         }
8777         // TODO: do boxfilter scale-down in shader?
8778         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8779         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8780         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8781
8782         // we now have a bloom image in the framebuffer
8783         // copy it into the bloom image texture for later processing
8784         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);
8785         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8786 }
8787
8788 void R_Bloom_CopyHDRTexture(void)
8789 {
8790         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);
8791         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8792 }
8793
8794 void R_Bloom_MakeTexture(void)
8795 {
8796         int x, range, dir;
8797         float xoffset, yoffset, r, brighten;
8798
8799         r_refdef.stats.bloom++;
8800
8801         R_ResetViewRendering2D();
8802
8803         // we have a bloom image in the framebuffer
8804         CHECKGLERROR
8805         R_SetViewport(&r_bloomstate.viewport);
8806
8807         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8808         {
8809                 x *= 2;
8810                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8811                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8812                 GL_Color(r,r,r,1);
8813                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8814                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8815                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8816                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8817
8818                 // copy the vertically blurred bloom view to a texture
8819                 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);
8820                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8821         }
8822
8823         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8824         brighten = r_bloom_brighten.value;
8825         if (r_hdr.integer)
8826                 brighten *= r_hdr_range.value;
8827         brighten = sqrt(brighten);
8828         if(range >= 1)
8829                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8830         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8831
8832         for (dir = 0;dir < 2;dir++)
8833         {
8834                 // blend on at multiple vertical offsets to achieve a vertical blur
8835                 // TODO: do offset blends using GLSL
8836                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8837                 GL_BlendFunc(GL_ONE, GL_ZERO);
8838                 for (x = -range;x <= range;x++)
8839                 {
8840                         if (!dir){xoffset = 0;yoffset = x;}
8841                         else {xoffset = x;yoffset = 0;}
8842                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8843                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8844                         // compute a texcoord array with the specified x and y offset
8845                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8846                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8847                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8848                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8849                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8850                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8851                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8852                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8853                         // this r value looks like a 'dot' particle, fading sharply to
8854                         // black at the edges
8855                         // (probably not realistic but looks good enough)
8856                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8857                         //r = brighten/(range*2+1);
8858                         r = brighten / (range * 2 + 1);
8859                         if(range >= 1)
8860                                 r *= (1 - x*x/(float)(range*range));
8861                         GL_Color(r, r, r, 1);
8862                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8863                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8864                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8865                         GL_BlendFunc(GL_ONE, GL_ONE);
8866                 }
8867
8868                 // copy the vertically blurred bloom view to a texture
8869                 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);
8870                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8871         }
8872 }
8873
8874 void R_HDR_RenderBloomTexture(void)
8875 {
8876         int oldwidth, oldheight;
8877         float oldcolorscale;
8878
8879         oldcolorscale = r_refdef.view.colorscale;
8880         oldwidth = r_refdef.view.width;
8881         oldheight = r_refdef.view.height;
8882         r_refdef.view.width = r_bloomstate.bloomwidth;
8883         r_refdef.view.height = r_bloomstate.bloomheight;
8884
8885         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8886         // TODO: add exposure compensation features
8887         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8888
8889         r_refdef.view.showdebug = false;
8890         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8891
8892         R_ResetViewRendering3D();
8893
8894         R_ClearScreen(r_refdef.fogenabled);
8895         if (r_timereport_active)
8896                 R_TimeReport("HDRclear");
8897
8898         R_View_Update();
8899         if (r_timereport_active)
8900                 R_TimeReport("visibility");
8901
8902         // only do secondary renders with HDR if r_hdr is 2 or higher
8903         r_waterstate.numwaterplanes = 0;
8904         if (r_waterstate.enabled && r_hdr.integer >= 2)
8905                 R_RenderWaterPlanes();
8906
8907         r_refdef.view.showdebug = true;
8908         R_RenderScene();
8909         r_waterstate.numwaterplanes = 0;
8910
8911         R_ResetViewRendering2D();
8912
8913         R_Bloom_CopyHDRTexture();
8914         R_Bloom_MakeTexture();
8915
8916         // restore the view settings
8917         r_refdef.view.width = oldwidth;
8918         r_refdef.view.height = oldheight;
8919         r_refdef.view.colorscale = oldcolorscale;
8920
8921         R_ResetViewRendering3D();
8922
8923         R_ClearScreen(r_refdef.fogenabled);
8924         if (r_timereport_active)
8925                 R_TimeReport("viewclear");
8926 }
8927
8928 static void R_BlendView(void)
8929 {
8930         unsigned int permutation;
8931         float uservecs[4][4];
8932
8933         switch (vid.renderpath)
8934         {
8935         case RENDERPATH_GL20:
8936         case RENDERPATH_CGGL:
8937         case RENDERPATH_D3D9:
8938         case RENDERPATH_D3D10:
8939         case RENDERPATH_D3D11:
8940                 permutation =
8941                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8942                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8943                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8944                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8945                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8946
8947                 if (r_bloomstate.texture_screen)
8948                 {
8949                         // make sure the buffer is available
8950                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8951
8952                         R_ResetViewRendering2D();
8953
8954                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8955                         {
8956                                 // declare variables
8957                                 float speed;
8958                                 static float avgspeed;
8959
8960                                 speed = VectorLength(cl.movement_velocity);
8961
8962                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8963                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8964
8965                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8966                                 speed = bound(0, speed, 1);
8967                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8968
8969                                 // calculate values into a standard alpha
8970                                 cl.motionbluralpha = 1 - exp(-
8971                                                 (
8972                                                  (r_motionblur.value * speed / 80)
8973                                                  +
8974                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8975                                                 )
8976                                                 /
8977                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8978                                            );
8979
8980                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8981                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8982                                 // apply the blur
8983                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8984                                 {
8985                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8986                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8987                                         switch(vid.renderpath)
8988                                         {
8989                                         case RENDERPATH_GL11:
8990                                         case RENDERPATH_GL13:
8991                                         case RENDERPATH_GL20:
8992                                         case RENDERPATH_CGGL:
8993                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8994                                                 break;
8995                                         case RENDERPATH_D3D9:
8996                                         case RENDERPATH_D3D10:
8997                                         case RENDERPATH_D3D11:
8998                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8999                                                 break;
9000                                         }
9001                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9002                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9003                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9004                                 }
9005                         }
9006
9007                         // copy view into the screen texture
9008                         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);
9009                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9010                 }
9011                 else if (!r_bloomstate.texture_bloom)
9012                 {
9013                         // we may still have to do view tint...
9014                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9015                         {
9016                                 // apply a color tint to the whole view
9017                                 R_ResetViewRendering2D();
9018                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9019                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9020                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9021                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9022                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9023                         }
9024                         break; // no screen processing, no bloom, skip it
9025                 }
9026
9027                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9028                 {
9029                         // render simple bloom effect
9030                         // copy the screen and shrink it and darken it for the bloom process
9031                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9032                         // make the bloom texture
9033                         R_Bloom_MakeTexture();
9034                 }
9035
9036 #if _MSC_VER >= 1400
9037 #define sscanf sscanf_s
9038 #endif
9039                 memset(uservecs, 0, sizeof(uservecs));
9040                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9041                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9042                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9043                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9044
9045                 R_ResetViewRendering2D();
9046                 GL_Color(1, 1, 1, 1);
9047                 GL_BlendFunc(GL_ONE, GL_ZERO);
9048
9049                 switch(vid.renderpath)
9050                 {
9051                 case RENDERPATH_GL20:
9052                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9053                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9054                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9055                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9056                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9057                         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]);
9058                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9059                         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]);
9060                         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]);
9061                         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]);
9062                         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]);
9063                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9064                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9065                         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);
9066                         break;
9067                 case RENDERPATH_CGGL:
9068 #ifdef SUPPORTCG
9069                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9070                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9071                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9072                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9073                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9074                         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
9075                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9076                         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
9077                         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
9078                         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
9079                         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
9080                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9081                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9082                         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);
9083 #endif
9084                         break;
9085                 case RENDERPATH_D3D9:
9086 #ifdef SUPPORTD3D
9087                         // 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...
9088                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9089                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9090                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9091                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9092                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9093                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9094                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9095                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9096                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9097                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9098                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9099                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9100                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9101                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9102 #endif
9103                         break;
9104                 case RENDERPATH_D3D10:
9105                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9106                         break;
9107                 case RENDERPATH_D3D11:
9108                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9109                         break;
9110                 default:
9111                         break;
9112                 }
9113                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9114                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9115                 break;
9116         case RENDERPATH_GL13:
9117         case RENDERPATH_GL11:
9118                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9119                 {
9120                         // apply a color tint to the whole view
9121                         R_ResetViewRendering2D();
9122                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9123                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9124                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9125                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9126                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9127                 }
9128                 break;
9129         }
9130 }
9131
9132 matrix4x4_t r_waterscrollmatrix;
9133
9134 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9135 {
9136         if (r_refdef.fog_density)
9137         {
9138                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9139                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9140                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9141
9142                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9143                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9144                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9145                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9146
9147                 {
9148                         vec3_t fogvec;
9149                         VectorCopy(r_refdef.fogcolor, fogvec);
9150                         //   color.rgb *= ContrastBoost * SceneBrightness;
9151                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9152                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9153                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9154                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9155                 }
9156         }
9157 }
9158
9159 void R_UpdateVariables(void)
9160 {
9161         R_Textures_Frame();
9162
9163         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9164
9165         r_refdef.farclip = r_farclip_base.value;
9166         if (r_refdef.scene.worldmodel)
9167                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9168         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9169
9170         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9171                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9172         r_refdef.polygonfactor = 0;
9173         r_refdef.polygonoffset = 0;
9174         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9175         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9176
9177         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9178         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9179         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9180         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9181         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9182         if (r_showsurfaces.integer)
9183         {
9184                 r_refdef.scene.rtworld = false;
9185                 r_refdef.scene.rtworldshadows = false;
9186                 r_refdef.scene.rtdlight = false;
9187                 r_refdef.scene.rtdlightshadows = false;
9188                 r_refdef.lightmapintensity = 0;
9189         }
9190
9191         if (gamemode == GAME_NEHAHRA)
9192         {
9193                 if (gl_fogenable.integer)
9194                 {
9195                         r_refdef.oldgl_fogenable = true;
9196                         r_refdef.fog_density = gl_fogdensity.value;
9197                         r_refdef.fog_red = gl_fogred.value;
9198                         r_refdef.fog_green = gl_foggreen.value;
9199                         r_refdef.fog_blue = gl_fogblue.value;
9200                         r_refdef.fog_alpha = 1;
9201                         r_refdef.fog_start = 0;
9202                         r_refdef.fog_end = gl_skyclip.value;
9203                         r_refdef.fog_height = 1<<30;
9204                         r_refdef.fog_fadedepth = 128;
9205                 }
9206                 else if (r_refdef.oldgl_fogenable)
9207                 {
9208                         r_refdef.oldgl_fogenable = false;
9209                         r_refdef.fog_density = 0;
9210                         r_refdef.fog_red = 0;
9211                         r_refdef.fog_green = 0;
9212                         r_refdef.fog_blue = 0;
9213                         r_refdef.fog_alpha = 0;
9214                         r_refdef.fog_start = 0;
9215                         r_refdef.fog_end = 0;
9216                         r_refdef.fog_height = 1<<30;
9217                         r_refdef.fog_fadedepth = 128;
9218                 }
9219         }
9220
9221         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9222         r_refdef.fog_start = max(0, r_refdef.fog_start);
9223         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9224
9225         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9226
9227         if (r_refdef.fog_density && r_drawfog.integer)
9228         {
9229                 r_refdef.fogenabled = true;
9230                 // this is the point where the fog reaches 0.9986 alpha, which we
9231                 // consider a good enough cutoff point for the texture
9232                 // (0.9986 * 256 == 255.6)
9233                 if (r_fog_exp2.integer)
9234                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9235                 else
9236                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9237                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9238                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9239                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9240                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9241                         R_BuildFogHeightTexture();
9242                 // fog color was already set
9243                 // update the fog texture
9244                 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)
9245                         R_BuildFogTexture();
9246                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9247                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9248         }
9249         else
9250                 r_refdef.fogenabled = false;
9251
9252         switch(vid.renderpath)
9253         {
9254         case RENDERPATH_GL20:
9255         case RENDERPATH_CGGL:
9256         case RENDERPATH_D3D9:
9257         case RENDERPATH_D3D10:
9258         case RENDERPATH_D3D11:
9259                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9260                 {
9261                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9262                         {
9263                                 // build GLSL gamma texture
9264 #define RAMPWIDTH 256
9265                                 unsigned short ramp[RAMPWIDTH * 3];
9266                                 unsigned char rampbgr[RAMPWIDTH][4];
9267                                 int i;
9268
9269                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9270
9271                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9272                                 for(i = 0; i < RAMPWIDTH; ++i)
9273                                 {
9274                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9275                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9276                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9277                                         rampbgr[i][3] = 0;
9278                                 }
9279                                 if (r_texture_gammaramps)
9280                                 {
9281                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9282                                 }
9283                                 else
9284                                 {
9285                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9286                                 }
9287                         }
9288                 }
9289                 else
9290                 {
9291                         // remove GLSL gamma texture
9292                 }
9293                 break;
9294         case RENDERPATH_GL13:
9295         case RENDERPATH_GL11:
9296                 break;
9297         }
9298 }
9299
9300 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9301 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9302 /*
9303 ================
9304 R_SelectScene
9305 ================
9306 */
9307 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9308         if( scenetype != r_currentscenetype ) {
9309                 // store the old scenetype
9310                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9311                 r_currentscenetype = scenetype;
9312                 // move in the new scene
9313                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9314         }
9315 }
9316
9317 /*
9318 ================
9319 R_GetScenePointer
9320 ================
9321 */
9322 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9323 {
9324         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9325         if( scenetype == r_currentscenetype ) {
9326                 return &r_refdef.scene;
9327         } else {
9328                 return &r_scenes_store[ scenetype ];
9329         }
9330 }
9331
9332 /*
9333 ================
9334 R_RenderView
9335 ================
9336 */
9337 void R_RenderView(void)
9338 {
9339         if (r_timereport_active)
9340                 R_TimeReport("start");
9341         r_textureframe++; // used only by R_GetCurrentTexture
9342         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9343
9344         if (!r_drawentities.integer)
9345                 r_refdef.scene.numentities = 0;
9346
9347         R_AnimCache_ClearCache();
9348         R_FrameData_NewFrame();
9349
9350         if (r_refdef.view.isoverlay)
9351         {
9352                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9353                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9354                 R_TimeReport("depthclear");
9355
9356                 r_refdef.view.showdebug = false;
9357
9358                 r_waterstate.enabled = false;
9359                 r_waterstate.numwaterplanes = 0;
9360
9361                 R_RenderScene();
9362
9363                 CHECKGLERROR
9364                 return;
9365         }
9366
9367         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9368                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9369
9370         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9371
9372         R_RenderView_UpdateViewVectors();
9373
9374         R_Shadow_UpdateWorldLightSelection();
9375
9376         R_Bloom_StartFrame();
9377         R_Water_StartFrame();
9378
9379         CHECKGLERROR
9380         if (r_timereport_active)
9381                 R_TimeReport("viewsetup");
9382
9383         R_ResetViewRendering3D();
9384
9385         if (r_refdef.view.clear || r_refdef.fogenabled)
9386         {
9387                 R_ClearScreen(r_refdef.fogenabled);
9388                 if (r_timereport_active)
9389                         R_TimeReport("viewclear");
9390         }
9391         r_refdef.view.clear = true;
9392
9393         // this produces a bloom texture to be used in R_BlendView() later
9394         if (r_hdr.integer && r_bloomstate.bloomwidth)
9395         {
9396                 R_HDR_RenderBloomTexture();
9397                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9398                 r_textureframe++; // used only by R_GetCurrentTexture
9399         }
9400
9401         r_refdef.view.showdebug = true;
9402
9403         R_View_Update();
9404         if (r_timereport_active)
9405                 R_TimeReport("visibility");
9406
9407         r_waterstate.numwaterplanes = 0;
9408         if (r_waterstate.enabled)
9409                 R_RenderWaterPlanes();
9410
9411         R_RenderScene();
9412         r_waterstate.numwaterplanes = 0;
9413
9414         R_BlendView();
9415         if (r_timereport_active)
9416                 R_TimeReport("blendview");
9417
9418         GL_Scissor(0, 0, vid.width, vid.height);
9419         GL_ScissorTest(false);
9420         CHECKGLERROR
9421 }
9422
9423 void R_RenderWaterPlanes(void)
9424 {
9425         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9426         {
9427                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9428                 if (r_timereport_active)
9429                         R_TimeReport("waterworld");
9430         }
9431
9432         // don't let sound skip if going slow
9433         if (r_refdef.scene.extraupdate)
9434                 S_ExtraUpdate ();
9435
9436         R_DrawModelsAddWaterPlanes();
9437         if (r_timereport_active)
9438                 R_TimeReport("watermodels");
9439
9440         if (r_waterstate.numwaterplanes)
9441         {
9442                 R_Water_ProcessPlanes();
9443                 if (r_timereport_active)
9444                         R_TimeReport("waterscenes");
9445         }
9446 }
9447
9448 extern void R_DrawLightningBeams (void);
9449 extern void VM_CL_AddPolygonsToMeshQueue (void);
9450 extern void R_DrawPortals (void);
9451 extern cvar_t cl_locs_show;
9452 static void R_DrawLocs(void);
9453 static void R_DrawEntityBBoxes(void);
9454 static void R_DrawModelDecals(void);
9455 extern void R_DrawModelShadows(void);
9456 extern void R_DrawModelShadowMaps(void);
9457 extern cvar_t cl_decals_newsystem;
9458 extern qboolean r_shadow_usingdeferredprepass;
9459 void R_RenderScene(void)
9460 {
9461         qboolean shadowmapping = false;
9462
9463         if (r_timereport_active)
9464                 R_TimeReport("beginscene");
9465
9466         r_refdef.stats.renders++;
9467
9468         R_UpdateFogColor();
9469
9470         // don't let sound skip if going slow
9471         if (r_refdef.scene.extraupdate)
9472                 S_ExtraUpdate ();
9473
9474         R_MeshQueue_BeginScene();
9475
9476         R_SkyStartFrame();
9477
9478         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);
9479
9480         if (r_timereport_active)
9481                 R_TimeReport("skystartframe");
9482
9483         if (cl.csqc_vidvars.drawworld)
9484         {
9485                 // don't let sound skip if going slow
9486                 if (r_refdef.scene.extraupdate)
9487                         S_ExtraUpdate ();
9488
9489                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9490                 {
9491                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9492                         if (r_timereport_active)
9493                                 R_TimeReport("worldsky");
9494                 }
9495
9496                 if (R_DrawBrushModelsSky() && r_timereport_active)
9497                         R_TimeReport("bmodelsky");
9498
9499                 if (skyrendermasked && skyrenderlater)
9500                 {
9501                         // we have to force off the water clipping plane while rendering sky
9502                         R_SetupView(false);
9503                         R_Sky();
9504                         R_SetupView(true);
9505                         if (r_timereport_active)
9506                                 R_TimeReport("sky");
9507                 }
9508         }
9509
9510         R_AnimCache_CacheVisibleEntities();
9511         if (r_timereport_active)
9512                 R_TimeReport("animation");
9513
9514         R_Shadow_PrepareLights();
9515         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9516                 R_Shadow_PrepareModelShadows();
9517         if (r_timereport_active)
9518                 R_TimeReport("preparelights");
9519
9520         if (R_Shadow_ShadowMappingEnabled())
9521                 shadowmapping = true;
9522
9523         if (r_shadow_usingdeferredprepass)
9524                 R_Shadow_DrawPrepass();
9525
9526         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9527         {
9528                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9529                 if (r_timereport_active)
9530                         R_TimeReport("worlddepth");
9531         }
9532         if (r_depthfirst.integer >= 2)
9533         {
9534                 R_DrawModelsDepth();
9535                 if (r_timereport_active)
9536                         R_TimeReport("modeldepth");
9537         }
9538
9539         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9540         {
9541                 R_DrawModelShadowMaps();
9542                 R_ResetViewRendering3D();
9543                 // don't let sound skip if going slow
9544                 if (r_refdef.scene.extraupdate)
9545                         S_ExtraUpdate ();
9546         }
9547
9548         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9549         {
9550                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9551                 if (r_timereport_active)
9552                         R_TimeReport("world");
9553         }
9554
9555         // don't let sound skip if going slow
9556         if (r_refdef.scene.extraupdate)
9557                 S_ExtraUpdate ();
9558
9559         R_DrawModels();
9560         if (r_timereport_active)
9561                 R_TimeReport("models");
9562
9563         // don't let sound skip if going slow
9564         if (r_refdef.scene.extraupdate)
9565                 S_ExtraUpdate ();
9566
9567         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9568         {
9569                 R_DrawModelShadows();
9570                 R_ResetViewRendering3D();
9571                 // don't let sound skip if going slow
9572                 if (r_refdef.scene.extraupdate)
9573                         S_ExtraUpdate ();
9574         }
9575
9576         if (!r_shadow_usingdeferredprepass)
9577         {
9578                 R_Shadow_DrawLights();
9579                 if (r_timereport_active)
9580                         R_TimeReport("rtlights");
9581         }
9582
9583         // don't let sound skip if going slow
9584         if (r_refdef.scene.extraupdate)
9585                 S_ExtraUpdate ();
9586
9587         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9588         {
9589                 R_DrawModelShadows();
9590                 R_ResetViewRendering3D();
9591                 // don't let sound skip if going slow
9592                 if (r_refdef.scene.extraupdate)
9593                         S_ExtraUpdate ();
9594         }
9595
9596         if (cl.csqc_vidvars.drawworld)
9597         {
9598                 if (cl_decals_newsystem.integer)
9599                 {
9600                         R_DrawModelDecals();
9601                         if (r_timereport_active)
9602                                 R_TimeReport("modeldecals");
9603                 }
9604                 else
9605                 {
9606                         R_DrawDecals();
9607                         if (r_timereport_active)
9608                                 R_TimeReport("decals");
9609                 }
9610
9611                 R_DrawParticles();
9612                 if (r_timereport_active)
9613                         R_TimeReport("particles");
9614
9615                 R_DrawExplosions();
9616                 if (r_timereport_active)
9617                         R_TimeReport("explosions");
9618
9619                 R_DrawLightningBeams();
9620                 if (r_timereport_active)
9621                         R_TimeReport("lightning");
9622         }
9623
9624         VM_CL_AddPolygonsToMeshQueue();
9625
9626         if (r_refdef.view.showdebug)
9627         {
9628                 if (cl_locs_show.integer)
9629                 {
9630                         R_DrawLocs();
9631                         if (r_timereport_active)
9632                                 R_TimeReport("showlocs");
9633                 }
9634
9635                 if (r_drawportals.integer)
9636                 {
9637                         R_DrawPortals();
9638                         if (r_timereport_active)
9639                                 R_TimeReport("portals");
9640                 }
9641
9642                 if (r_showbboxes.value > 0)
9643                 {
9644                         R_DrawEntityBBoxes();
9645                         if (r_timereport_active)
9646                                 R_TimeReport("bboxes");
9647                 }
9648         }
9649
9650         R_MeshQueue_RenderTransparent();
9651         if (r_timereport_active)
9652                 R_TimeReport("drawtrans");
9653
9654         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))
9655         {
9656                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9657                 if (r_timereport_active)
9658                         R_TimeReport("worlddebug");
9659                 R_DrawModelsDebug();
9660                 if (r_timereport_active)
9661                         R_TimeReport("modeldebug");
9662         }
9663
9664         if (cl.csqc_vidvars.drawworld)
9665         {
9666                 R_Shadow_DrawCoronas();
9667                 if (r_timereport_active)
9668                         R_TimeReport("coronas");
9669         }
9670
9671         // don't let sound skip if going slow
9672         if (r_refdef.scene.extraupdate)
9673                 S_ExtraUpdate ();
9674
9675         R_ResetViewRendering2D();
9676 }
9677
9678 static const unsigned short bboxelements[36] =
9679 {
9680         5, 1, 3, 5, 3, 7,
9681         6, 2, 0, 6, 0, 4,
9682         7, 3, 2, 7, 2, 6,
9683         4, 0, 1, 4, 1, 5,
9684         4, 5, 7, 4, 7, 6,
9685         1, 0, 2, 1, 2, 3,
9686 };
9687
9688 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9689 {
9690         int i;
9691         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9692
9693         RSurf_ActiveWorldEntity();
9694
9695         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9696         GL_DepthMask(false);
9697         GL_DepthRange(0, 1);
9698         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9699         R_Mesh_ResetTextureState();
9700
9701         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9702         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9703         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9704         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9705         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9706         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9707         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9708         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9709         R_FillColors(color4f, 8, cr, cg, cb, ca);
9710         if (r_refdef.fogenabled)
9711         {
9712                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9713                 {
9714                         f1 = RSurf_FogVertex(v);
9715                         f2 = 1 - f1;
9716                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9717                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9718                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9719                 }
9720         }
9721         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9722         R_Mesh_ResetTextureState();
9723         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9724         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9725 }
9726
9727 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9728 {
9729         int i;
9730         float color[4];
9731         prvm_edict_t *edict;
9732         prvm_prog_t *prog_save = prog;
9733
9734         // this function draws bounding boxes of server entities
9735         if (!sv.active)
9736                 return;
9737
9738         GL_CullFace(GL_NONE);
9739         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9740
9741         prog = 0;
9742         SV_VM_Begin();
9743         for (i = 0;i < numsurfaces;i++)
9744         {
9745                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9746                 switch ((int)edict->fields.server->solid)
9747                 {
9748                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9749                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9750                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9751                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9752                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9753                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9754                 }
9755                 color[3] *= r_showbboxes.value;
9756                 color[3] = bound(0, color[3], 1);
9757                 GL_DepthTest(!r_showdisabledepthtest.integer);
9758                 GL_CullFace(r_refdef.view.cullface_front);
9759                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9760         }
9761         SV_VM_End();
9762         prog = prog_save;
9763 }
9764
9765 static void R_DrawEntityBBoxes(void)
9766 {
9767         int i;
9768         prvm_edict_t *edict;
9769         vec3_t center;
9770         prvm_prog_t *prog_save = prog;
9771
9772         // this function draws bounding boxes of server entities
9773         if (!sv.active)
9774                 return;
9775
9776         prog = 0;
9777         SV_VM_Begin();
9778         for (i = 0;i < prog->num_edicts;i++)
9779         {
9780                 edict = PRVM_EDICT_NUM(i);
9781                 if (edict->priv.server->free)
9782                         continue;
9783                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9784                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9785                         continue;
9786                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9787                         continue;
9788                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9789                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9790         }
9791         SV_VM_End();
9792         prog = prog_save;
9793 }
9794
9795 static const int nomodelelement3i[24] =
9796 {
9797         5, 2, 0,
9798         5, 1, 2,
9799         5, 0, 3,
9800         5, 3, 1,
9801         0, 2, 4,
9802         2, 1, 4,
9803         3, 0, 4,
9804         1, 3, 4
9805 };
9806
9807 static const unsigned short nomodelelement3s[24] =
9808 {
9809         5, 2, 0,
9810         5, 1, 2,
9811         5, 0, 3,
9812         5, 3, 1,
9813         0, 2, 4,
9814         2, 1, 4,
9815         3, 0, 4,
9816         1, 3, 4
9817 };
9818
9819 static const float nomodelvertex3f[6*3] =
9820 {
9821         -16,   0,   0,
9822          16,   0,   0,
9823           0, -16,   0,
9824           0,  16,   0,
9825           0,   0, -16,
9826           0,   0,  16
9827 };
9828
9829 static const float nomodelcolor4f[6*4] =
9830 {
9831         0.0f, 0.0f, 0.5f, 1.0f,
9832         0.0f, 0.0f, 0.5f, 1.0f,
9833         0.0f, 0.5f, 0.0f, 1.0f,
9834         0.0f, 0.5f, 0.0f, 1.0f,
9835         0.5f, 0.0f, 0.0f, 1.0f,
9836         0.5f, 0.0f, 0.0f, 1.0f
9837 };
9838
9839 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9840 {
9841         int i;
9842         float f1, f2, *c;
9843         float color4f[6*4];
9844
9845         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);
9846
9847         // this is only called once per entity so numsurfaces is always 1, and
9848         // surfacelist is always {0}, so this code does not handle batches
9849
9850         if (rsurface.ent_flags & RENDER_ADDITIVE)
9851         {
9852                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9853                 GL_DepthMask(false);
9854         }
9855         else if (rsurface.colormod[3] < 1)
9856         {
9857                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9858                 GL_DepthMask(false);
9859         }
9860         else
9861         {
9862                 GL_BlendFunc(GL_ONE, GL_ZERO);
9863                 GL_DepthMask(true);
9864         }
9865         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9866         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9867         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9868         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9869         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9870         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9871         for (i = 0, c = color4f;i < 6;i++, c += 4)
9872         {
9873                 c[0] *= rsurface.colormod[0];
9874                 c[1] *= rsurface.colormod[1];
9875                 c[2] *= rsurface.colormod[2];
9876                 c[3] *= rsurface.colormod[3];
9877         }
9878         if (r_refdef.fogenabled)
9879         {
9880                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9881                 {
9882                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9883                         f2 = 1 - f1;
9884                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9885                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9886                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9887                 }
9888         }
9889         R_Mesh_ResetTextureState();
9890         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9891         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9892 }
9893
9894 void R_DrawNoModel(entity_render_t *ent)
9895 {
9896         vec3_t org;
9897         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9898         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9899                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9900         else
9901                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9902 }
9903
9904 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9905 {
9906         vec3_t right1, right2, diff, normal;
9907
9908         VectorSubtract (org2, org1, normal);
9909
9910         // calculate 'right' vector for start
9911         VectorSubtract (r_refdef.view.origin, org1, diff);
9912         CrossProduct (normal, diff, right1);
9913         VectorNormalize (right1);
9914
9915         // calculate 'right' vector for end
9916         VectorSubtract (r_refdef.view.origin, org2, diff);
9917         CrossProduct (normal, diff, right2);
9918         VectorNormalize (right2);
9919
9920         vert[ 0] = org1[0] + width * right1[0];
9921         vert[ 1] = org1[1] + width * right1[1];
9922         vert[ 2] = org1[2] + width * right1[2];
9923         vert[ 3] = org1[0] - width * right1[0];
9924         vert[ 4] = org1[1] - width * right1[1];
9925         vert[ 5] = org1[2] - width * right1[2];
9926         vert[ 6] = org2[0] - width * right2[0];
9927         vert[ 7] = org2[1] - width * right2[1];
9928         vert[ 8] = org2[2] - width * right2[2];
9929         vert[ 9] = org2[0] + width * right2[0];
9930         vert[10] = org2[1] + width * right2[1];
9931         vert[11] = org2[2] + width * right2[2];
9932 }
9933
9934 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)
9935 {
9936         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9937         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9938         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9939         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9940         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9941         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9942         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9943         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9944         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9945         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9946         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9947         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9948 }
9949
9950 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9951 {
9952         int i;
9953         float *vertex3f;
9954         float v[3];
9955         VectorSet(v, x, y, z);
9956         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9957                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9958                         break;
9959         if (i == mesh->numvertices)
9960         {
9961                 if (mesh->numvertices < mesh->maxvertices)
9962                 {
9963                         VectorCopy(v, vertex3f);
9964                         mesh->numvertices++;
9965                 }
9966                 return mesh->numvertices;
9967         }
9968         else
9969                 return i;
9970 }
9971
9972 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9973 {
9974         int i;
9975         int *e, element[3];
9976         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9977         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9978         e = mesh->element3i + mesh->numtriangles * 3;
9979         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9980         {
9981                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9982                 if (mesh->numtriangles < mesh->maxtriangles)
9983                 {
9984                         *e++ = element[0];
9985                         *e++ = element[1];
9986                         *e++ = element[2];
9987                         mesh->numtriangles++;
9988                 }
9989                 element[1] = element[2];
9990         }
9991 }
9992
9993 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9994 {
9995         int i;
9996         int *e, element[3];
9997         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9998         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9999         e = mesh->element3i + mesh->numtriangles * 3;
10000         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10001         {
10002                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10003                 if (mesh->numtriangles < mesh->maxtriangles)
10004                 {
10005                         *e++ = element[0];
10006                         *e++ = element[1];
10007                         *e++ = element[2];
10008                         mesh->numtriangles++;
10009                 }
10010                 element[1] = element[2];
10011         }
10012 }
10013
10014 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10015 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10016 {
10017         int planenum, planenum2;
10018         int w;
10019         int tempnumpoints;
10020         mplane_t *plane, *plane2;
10021         double maxdist;
10022         double temppoints[2][256*3];
10023         // figure out how large a bounding box we need to properly compute this brush
10024         maxdist = 0;
10025         for (w = 0;w < numplanes;w++)
10026                 maxdist = max(maxdist, fabs(planes[w].dist));
10027         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10028         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10029         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10030         {
10031                 w = 0;
10032                 tempnumpoints = 4;
10033                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10034                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10035                 {
10036                         if (planenum2 == planenum)
10037                                 continue;
10038                         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);
10039                         w = !w;
10040                 }
10041                 if (tempnumpoints < 3)
10042                         continue;
10043                 // generate elements forming a triangle fan for this polygon
10044                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10045         }
10046 }
10047
10048 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)
10049 {
10050         texturelayer_t *layer;
10051         layer = t->currentlayers + t->currentnumlayers++;
10052         layer->type = type;
10053         layer->depthmask = depthmask;
10054         layer->blendfunc1 = blendfunc1;
10055         layer->blendfunc2 = blendfunc2;
10056         layer->texture = texture;
10057         layer->texmatrix = *matrix;
10058         layer->color[0] = r;
10059         layer->color[1] = g;
10060         layer->color[2] = b;
10061         layer->color[3] = a;
10062 }
10063
10064 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10065 {
10066         if(parms[0] == 0 && parms[1] == 0)
10067                 return false;
10068         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10069                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10070                         return false;
10071         return true;
10072 }
10073
10074 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10075 {
10076         double index, f;
10077         index = parms[2] + r_refdef.scene.time * parms[3];
10078         index -= floor(index);
10079         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10080         {
10081         default:
10082         case Q3WAVEFUNC_NONE:
10083         case Q3WAVEFUNC_NOISE:
10084         case Q3WAVEFUNC_COUNT:
10085                 f = 0;
10086                 break;
10087         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10088         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10089         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10090         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10091         case Q3WAVEFUNC_TRIANGLE:
10092                 index *= 4;
10093                 f = index - floor(index);
10094                 if (index < 1)
10095                         f = f;
10096                 else if (index < 2)
10097                         f = 1 - f;
10098                 else if (index < 3)
10099                         f = -f;
10100                 else
10101                         f = -(1 - f);
10102                 break;
10103         }
10104         f = parms[0] + parms[1] * f;
10105         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10106                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10107         return (float) f;
10108 }
10109
10110 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10111 {
10112         int w, h, idx;
10113         float f;
10114         float tcmat[12];
10115         matrix4x4_t matrix, temp;
10116         switch(tcmod->tcmod)
10117         {
10118                 case Q3TCMOD_COUNT:
10119                 case Q3TCMOD_NONE:
10120                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10121                                 matrix = r_waterscrollmatrix;
10122                         else
10123                                 matrix = identitymatrix;
10124                         break;
10125                 case Q3TCMOD_ENTITYTRANSLATE:
10126                         // this is used in Q3 to allow the gamecode to control texcoord
10127                         // scrolling on the entity, which is not supported in darkplaces yet.
10128                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10129                         break;
10130                 case Q3TCMOD_ROTATE:
10131                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10132                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10133                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10134                         break;
10135                 case Q3TCMOD_SCALE:
10136                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10137                         break;
10138                 case Q3TCMOD_SCROLL:
10139                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10140                         break;
10141                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10142                         w = (int) tcmod->parms[0];
10143                         h = (int) tcmod->parms[1];
10144                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10145                         f = f - floor(f);
10146                         idx = (int) floor(f * w * h);
10147                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10148                         break;
10149                 case Q3TCMOD_STRETCH:
10150                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10151                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10152                         break;
10153                 case Q3TCMOD_TRANSFORM:
10154                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10155                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10156                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10157                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10158                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10159                         break;
10160                 case Q3TCMOD_TURBULENT:
10161                         // this is handled in the RSurf_PrepareVertices function
10162                         matrix = identitymatrix;
10163                         break;
10164         }
10165         temp = *texmatrix;
10166         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10167 }
10168
10169 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10170 {
10171         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10172         char name[MAX_QPATH];
10173         skinframe_t *skinframe;
10174         unsigned char pixels[296*194];
10175         strlcpy(cache->name, skinname, sizeof(cache->name));
10176         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10177         if (developer_loading.integer)
10178                 Con_Printf("loading %s\n", name);
10179         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10180         if (!skinframe || !skinframe->base)
10181         {
10182                 unsigned char *f;
10183                 fs_offset_t filesize;
10184                 skinframe = NULL;
10185                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10186                 if (f)
10187                 {
10188                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10189                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10190                         Mem_Free(f);
10191                 }
10192         }
10193         cache->skinframe = skinframe;
10194 }
10195
10196 texture_t *R_GetCurrentTexture(texture_t *t)
10197 {
10198         int i;
10199         const entity_render_t *ent = rsurface.entity;
10200         dp_model_t *model = ent->model;
10201         q3shaderinfo_layer_tcmod_t *tcmod;
10202
10203         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10204                 return t->currentframe;
10205         t->update_lastrenderframe = r_textureframe;
10206         t->update_lastrenderentity = (void *)ent;
10207
10208         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10209                 t->camera_entity = ent->entitynumber;
10210         else
10211                 t->camera_entity = 0;
10212
10213         // switch to an alternate material if this is a q1bsp animated material
10214         {
10215                 texture_t *texture = t;
10216                 int s = rsurface.ent_skinnum;
10217                 if ((unsigned int)s >= (unsigned int)model->numskins)
10218                         s = 0;
10219                 if (model->skinscenes)
10220                 {
10221                         if (model->skinscenes[s].framecount > 1)
10222                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10223                         else
10224                                 s = model->skinscenes[s].firstframe;
10225                 }
10226                 if (s > 0)
10227                         t = t + s * model->num_surfaces;
10228                 if (t->animated)
10229                 {
10230                         // use an alternate animation if the entity's frame is not 0,
10231                         // and only if the texture has an alternate animation
10232                         if (rsurface.ent_alttextures && t->anim_total[1])
10233                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10234                         else
10235                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10236                 }
10237                 texture->currentframe = t;
10238         }
10239
10240         // update currentskinframe to be a qw skin or animation frame
10241         if (rsurface.ent_qwskin >= 0)
10242         {
10243                 i = rsurface.ent_qwskin;
10244                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10245                 {
10246                         r_qwskincache_size = cl.maxclients;
10247                         if (r_qwskincache)
10248                                 Mem_Free(r_qwskincache);
10249                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10250                 }
10251                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10252                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10253                 t->currentskinframe = r_qwskincache[i].skinframe;
10254                 if (t->currentskinframe == NULL)
10255                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10256         }
10257         else if (t->numskinframes >= 2)
10258                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10259         if (t->backgroundnumskinframes >= 2)
10260                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10261
10262         t->currentmaterialflags = t->basematerialflags;
10263         t->currentalpha = rsurface.colormod[3];
10264         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10265                 t->currentalpha *= r_wateralpha.value;
10266         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10267                 t->currentalpha *= t->r_water_wateralpha;
10268         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10269                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10270         if (!(rsurface.ent_flags & RENDER_LIGHT))
10271                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10272         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10273         {
10274                 // pick a model lighting mode
10275                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10276                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10277                 else
10278                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10279         }
10280         if (rsurface.ent_flags & RENDER_ADDITIVE)
10281                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10282         else if (t->currentalpha < 1)
10283                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10284         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10285                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10286         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10287                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10288         if (t->backgroundnumskinframes)
10289                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10290         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10291         {
10292                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10293                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10294         }
10295         else
10296                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10297         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10298                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10299
10300         // there is no tcmod
10301         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10302         {
10303                 t->currenttexmatrix = r_waterscrollmatrix;
10304                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10305         }
10306         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10307         {
10308                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10309                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10310         }
10311
10312         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10313                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10314         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10315                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10316
10317         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10318         if (t->currentskinframe->qpixels)
10319                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10320         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10321         if (!t->basetexture)
10322                 t->basetexture = r_texture_notexture;
10323         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10324         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10325         t->nmaptexture = t->currentskinframe->nmap;
10326         if (!t->nmaptexture)
10327                 t->nmaptexture = r_texture_blanknormalmap;
10328         t->glosstexture = r_texture_black;
10329         t->glowtexture = t->currentskinframe->glow;
10330         t->fogtexture = t->currentskinframe->fog;
10331         t->reflectmasktexture = t->currentskinframe->reflect;
10332         if (t->backgroundnumskinframes)
10333         {
10334                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10335                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10336                 t->backgroundglosstexture = r_texture_black;
10337                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10338                 if (!t->backgroundnmaptexture)
10339                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10340         }
10341         else
10342         {
10343                 t->backgroundbasetexture = r_texture_white;
10344                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10345                 t->backgroundglosstexture = r_texture_black;
10346                 t->backgroundglowtexture = NULL;
10347         }
10348         t->specularpower = r_shadow_glossexponent.value;
10349         // TODO: store reference values for these in the texture?
10350         t->specularscale = 0;
10351         if (r_shadow_gloss.integer > 0)
10352         {
10353                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10354                 {
10355                         if (r_shadow_glossintensity.value > 0)
10356                         {
10357                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10358                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10359                                 t->specularscale = r_shadow_glossintensity.value;
10360                         }
10361                 }
10362                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10363                 {
10364                         t->glosstexture = r_texture_white;
10365                         t->backgroundglosstexture = r_texture_white;
10366                         t->specularscale = r_shadow_gloss2intensity.value;
10367                         t->specularpower = r_shadow_gloss2exponent.value;
10368                 }
10369         }
10370         t->specularscale *= t->specularscalemod;
10371         t->specularpower *= t->specularpowermod;
10372
10373         // lightmaps mode looks bad with dlights using actual texturing, so turn
10374         // off the colormap and glossmap, but leave the normalmap on as it still
10375         // accurately represents the shading involved
10376         if (gl_lightmaps.integer)
10377         {
10378                 t->basetexture = r_texture_grey128;
10379                 t->pantstexture = r_texture_black;
10380                 t->shirttexture = r_texture_black;
10381                 t->nmaptexture = r_texture_blanknormalmap;
10382                 t->glosstexture = r_texture_black;
10383                 t->glowtexture = NULL;
10384                 t->fogtexture = NULL;
10385                 t->reflectmasktexture = NULL;
10386                 t->backgroundbasetexture = NULL;
10387                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10388                 t->backgroundglosstexture = r_texture_black;
10389                 t->backgroundglowtexture = NULL;
10390                 t->specularscale = 0;
10391                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10392         }
10393
10394         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10395         VectorClear(t->dlightcolor);
10396         t->currentnumlayers = 0;
10397         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10398         {
10399                 int blendfunc1, blendfunc2;
10400                 qboolean depthmask;
10401                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10402                 {
10403                         blendfunc1 = GL_SRC_ALPHA;
10404                         blendfunc2 = GL_ONE;
10405                 }
10406                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10407                 {
10408                         blendfunc1 = GL_SRC_ALPHA;
10409                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10410                 }
10411                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10412                 {
10413                         blendfunc1 = t->customblendfunc[0];
10414                         blendfunc2 = t->customblendfunc[1];
10415                 }
10416                 else
10417                 {
10418                         blendfunc1 = GL_ONE;
10419                         blendfunc2 = GL_ZERO;
10420                 }
10421                 // don't colormod evilblend textures
10422                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10423                         VectorSet(t->lightmapcolor, 1, 1, 1);
10424                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10425                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10426                 {
10427                         // fullbright is not affected by r_refdef.lightmapintensity
10428                         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]);
10429                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10430                                 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]);
10431                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10432                                 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]);
10433                 }
10434                 else
10435                 {
10436                         vec3_t ambientcolor;
10437                         float colorscale;
10438                         // set the color tint used for lights affecting this surface
10439                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10440                         colorscale = 2;
10441                         // q3bsp has no lightmap updates, so the lightstylevalue that
10442                         // would normally be baked into the lightmap must be
10443                         // applied to the color
10444                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10445                         if (model->type == mod_brushq3)
10446                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10447                         colorscale *= r_refdef.lightmapintensity;
10448                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10449                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10450                         // basic lit geometry
10451                         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]);
10452                         // add pants/shirt if needed
10453                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10454                                 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]);
10455                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10456                                 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]);
10457                         // now add ambient passes if needed
10458                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10459                         {
10460                                 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]);
10461                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10462                                         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]);
10463                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10464                                         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]);
10465                         }
10466                 }
10467                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10468                         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]);
10469                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10470                 {
10471                         // if this is opaque use alpha blend which will darken the earlier
10472                         // passes cheaply.
10473                         //
10474                         // if this is an alpha blended material, all the earlier passes
10475                         // were darkened by fog already, so we only need to add the fog
10476                         // color ontop through the fog mask texture
10477                         //
10478                         // if this is an additive blended material, all the earlier passes
10479                         // were darkened by fog already, and we should not add fog color
10480                         // (because the background was not darkened, there is no fog color
10481                         // that was lost behind it).
10482                         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]);
10483                 }
10484         }
10485
10486         return t->currentframe;
10487 }
10488
10489 rsurfacestate_t rsurface;
10490
10491 void R_Mesh_ResizeArrays(int newvertices)
10492 {
10493         unsigned char *base;
10494         size_t size;
10495         if (rsurface.array_size >= newvertices)
10496                 return;
10497         if (rsurface.array_base)
10498                 Mem_Free(rsurface.array_base);
10499         rsurface.array_size = (newvertices + 1023) & ~1023;
10500         size = 0;
10501         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10502         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10503         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10504         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10505         size += rsurface.array_size * sizeof(float[3]);
10506         size += rsurface.array_size * sizeof(float[3]);
10507         size += rsurface.array_size * sizeof(float[3]);
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[4]);
10514         size += rsurface.array_size * sizeof(float[2]);
10515         size += rsurface.array_size * sizeof(float[2]);
10516         size += rsurface.array_size * sizeof(float[4]);
10517         size += rsurface.array_size * sizeof(int[3]);
10518         size += rsurface.array_size * sizeof(unsigned short[3]);
10519         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10520         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10521         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10522         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10523         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10524         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10525         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10526         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10527         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10528         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10529         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10530         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10531         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10532         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10533         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10534         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10535         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10536         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10537         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10538 }
10539
10540 void RSurf_ActiveWorldEntity(void)
10541 {
10542         dp_model_t *model = r_refdef.scene.worldmodel;
10543         //if (rsurface.entity == r_refdef.scene.worldentity)
10544         //      return;
10545         rsurface.entity = r_refdef.scene.worldentity;
10546         rsurface.skeleton = NULL;
10547         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10548         rsurface.ent_skinnum = 0;
10549         rsurface.ent_qwskin = -1;
10550         rsurface.ent_shadertime = 0;
10551         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10552         if (rsurface.array_size < model->surfmesh.num_vertices)
10553                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10554         rsurface.matrix = identitymatrix;
10555         rsurface.inversematrix = identitymatrix;
10556         rsurface.matrixscale = 1;
10557         rsurface.inversematrixscale = 1;
10558         R_EntityMatrix(&identitymatrix);
10559         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10560         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10561         rsurface.fograngerecip = r_refdef.fograngerecip;
10562         rsurface.fogheightfade = r_refdef.fogheightfade;
10563         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10564         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10565         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10566         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10567         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10568         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10569         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10570         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10571         rsurface.colormod[3] = 1;
10572         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);
10573         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10574         rsurface.frameblend[0].lerp = 1;
10575         rsurface.ent_alttextures = false;
10576         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10577         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10578         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10579         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10580         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10581         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10582         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10583         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10584         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10585         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10586         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10587         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10588         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10589         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10590         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10591         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10592         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10593         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10594         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10595         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10596         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10597         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10598         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10599         rsurface.modelelement3i = model->surfmesh.data_element3i;
10600         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10601         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10602         rsurface.modelelement3s = model->surfmesh.data_element3s;
10603         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10604         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10605         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10606         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10607         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10608         rsurface.modelsurfaces = model->data_surfaces;
10609         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10610         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10611         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10612         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10613         rsurface.modelgeneratedvertex = false;
10614         rsurface.batchgeneratedvertex = false;
10615         rsurface.batchfirstvertex = 0;
10616         rsurface.batchnumvertices = 0;
10617         rsurface.batchfirsttriangle = 0;
10618         rsurface.batchnumtriangles = 0;
10619         rsurface.batchvertex3f  = NULL;
10620         rsurface.batchvertex3f_vertexbuffer = NULL;
10621         rsurface.batchvertex3f_bufferoffset = 0;
10622         rsurface.batchsvector3f = NULL;
10623         rsurface.batchsvector3f_vertexbuffer = NULL;
10624         rsurface.batchsvector3f_bufferoffset = 0;
10625         rsurface.batchtvector3f = NULL;
10626         rsurface.batchtvector3f_vertexbuffer = NULL;
10627         rsurface.batchtvector3f_bufferoffset = 0;
10628         rsurface.batchnormal3f  = NULL;
10629         rsurface.batchnormal3f_vertexbuffer = NULL;
10630         rsurface.batchnormal3f_bufferoffset = 0;
10631         rsurface.batchlightmapcolor4f = NULL;
10632         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10633         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10634         rsurface.batchtexcoordtexture2f = NULL;
10635         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10636         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10637         rsurface.batchtexcoordlightmap2f = NULL;
10638         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10639         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10640         rsurface.batchvertexmesh = NULL;
10641         rsurface.batchvertexmeshbuffer = NULL;
10642         rsurface.batchvertexposition = NULL;
10643         rsurface.batchvertexpositionbuffer = NULL;
10644         rsurface.batchelement3i = NULL;
10645         rsurface.batchelement3i_indexbuffer = NULL;
10646         rsurface.batchelement3i_bufferoffset = 0;
10647         rsurface.batchelement3s = NULL;
10648         rsurface.batchelement3s_indexbuffer = NULL;
10649         rsurface.batchelement3s_bufferoffset = 0;
10650         rsurface.passcolor4f = NULL;
10651         rsurface.passcolor4f_vertexbuffer = NULL;
10652         rsurface.passcolor4f_bufferoffset = 0;
10653 }
10654
10655 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10656 {
10657         dp_model_t *model = ent->model;
10658         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10659         //      return;
10660         rsurface.entity = (entity_render_t *)ent;
10661         rsurface.skeleton = ent->skeleton;
10662         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10663         rsurface.ent_skinnum = ent->skinnum;
10664         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;
10665         rsurface.ent_shadertime = ent->shadertime;
10666         rsurface.ent_flags = ent->flags;
10667         if (rsurface.array_size < model->surfmesh.num_vertices)
10668                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10669         rsurface.matrix = ent->matrix;
10670         rsurface.inversematrix = ent->inversematrix;
10671         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10672         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10673         R_EntityMatrix(&rsurface.matrix);
10674         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10675         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10676         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10677         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10678         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10679         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10680         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10681         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10682         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10683         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10684         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10685         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10686         rsurface.colormod[3] = ent->alpha;
10687         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10688         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10689         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10690         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10691         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10692         if (ent->model->brush.submodel && !prepass)
10693         {
10694                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10695                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10696         }
10697         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10698         {
10699                 if (ent->animcache_vertex3f && !r_framedata_failed)
10700                 {
10701                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10702                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10703                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10704                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10705                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10706                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10707                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10708                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10709                 }
10710                 else if (wanttangents)
10711                 {
10712                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10713                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10714                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10715                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10716                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10717                         rsurface.modelvertexmesh = NULL;
10718                         rsurface.modelvertexmeshbuffer = NULL;
10719                         rsurface.modelvertexposition = NULL;
10720                         rsurface.modelvertexpositionbuffer = NULL;
10721                 }
10722                 else if (wantnormals)
10723                 {
10724                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10725                         rsurface.modelsvector3f = NULL;
10726                         rsurface.modeltvector3f = NULL;
10727                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10728                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10729                         rsurface.modelvertexmesh = NULL;
10730                         rsurface.modelvertexmeshbuffer = NULL;
10731                         rsurface.modelvertexposition = NULL;
10732                         rsurface.modelvertexpositionbuffer = NULL;
10733                 }
10734                 else
10735                 {
10736                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10737                         rsurface.modelsvector3f = NULL;
10738                         rsurface.modeltvector3f = NULL;
10739                         rsurface.modelnormal3f = NULL;
10740                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10741                         rsurface.modelvertexmesh = NULL;
10742                         rsurface.modelvertexmeshbuffer = NULL;
10743                         rsurface.modelvertexposition = NULL;
10744                         rsurface.modelvertexpositionbuffer = NULL;
10745                 }
10746                 rsurface.modelvertex3f_vertexbuffer = 0;
10747                 rsurface.modelvertex3f_bufferoffset = 0;
10748                 rsurface.modelsvector3f_vertexbuffer = 0;
10749                 rsurface.modelsvector3f_bufferoffset = 0;
10750                 rsurface.modeltvector3f_vertexbuffer = 0;
10751                 rsurface.modeltvector3f_bufferoffset = 0;
10752                 rsurface.modelnormal3f_vertexbuffer = 0;
10753                 rsurface.modelnormal3f_bufferoffset = 0;
10754                 rsurface.modelgeneratedvertex = true;
10755         }
10756         else
10757         {
10758                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10759                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10760                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10761                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10762                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10763                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10764                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10765                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10766                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10767                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10768                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10769                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10770                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10771                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10772                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10773                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10774                 rsurface.modelgeneratedvertex = false;
10775         }
10776         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10777         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10778         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10779         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10780         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10781         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10782         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10783         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10784         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10785         rsurface.modelelement3i = model->surfmesh.data_element3i;
10786         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10787         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10788         rsurface.modelelement3s = model->surfmesh.data_element3s;
10789         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10790         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10791         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10792         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10793         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10794         rsurface.modelsurfaces = model->data_surfaces;
10795         rsurface.batchgeneratedvertex = false;
10796         rsurface.batchfirstvertex = 0;
10797         rsurface.batchnumvertices = 0;
10798         rsurface.batchfirsttriangle = 0;
10799         rsurface.batchnumtriangles = 0;
10800         rsurface.batchvertex3f  = NULL;
10801         rsurface.batchvertex3f_vertexbuffer = NULL;
10802         rsurface.batchvertex3f_bufferoffset = 0;
10803         rsurface.batchsvector3f = NULL;
10804         rsurface.batchsvector3f_vertexbuffer = NULL;
10805         rsurface.batchsvector3f_bufferoffset = 0;
10806         rsurface.batchtvector3f = NULL;
10807         rsurface.batchtvector3f_vertexbuffer = NULL;
10808         rsurface.batchtvector3f_bufferoffset = 0;
10809         rsurface.batchnormal3f  = NULL;
10810         rsurface.batchnormal3f_vertexbuffer = NULL;
10811         rsurface.batchnormal3f_bufferoffset = 0;
10812         rsurface.batchlightmapcolor4f = NULL;
10813         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10814         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10815         rsurface.batchtexcoordtexture2f = NULL;
10816         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10817         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10818         rsurface.batchtexcoordlightmap2f = NULL;
10819         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10820         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10821         rsurface.batchvertexmesh = NULL;
10822         rsurface.batchvertexmeshbuffer = NULL;
10823         rsurface.batchvertexposition = NULL;
10824         rsurface.batchvertexpositionbuffer = NULL;
10825         rsurface.batchelement3i = NULL;
10826         rsurface.batchelement3i_indexbuffer = NULL;
10827         rsurface.batchelement3i_bufferoffset = 0;
10828         rsurface.batchelement3s = NULL;
10829         rsurface.batchelement3s_indexbuffer = NULL;
10830         rsurface.batchelement3s_bufferoffset = 0;
10831         rsurface.passcolor4f = NULL;
10832         rsurface.passcolor4f_vertexbuffer = NULL;
10833         rsurface.passcolor4f_bufferoffset = 0;
10834 }
10835
10836 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)
10837 {
10838         int i;
10839
10840         rsurface.entity = r_refdef.scene.worldentity;
10841         rsurface.skeleton = NULL;
10842         rsurface.ent_skinnum = 0;
10843         rsurface.ent_qwskin = -1;
10844         rsurface.ent_shadertime = shadertime;
10845         rsurface.ent_flags = entflags;
10846         rsurface.modelnumvertices = numvertices;
10847         rsurface.modelnumtriangles = numtriangles;
10848         if (rsurface.array_size < rsurface.modelnumvertices)
10849                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10850         rsurface.matrix = *matrix;
10851         rsurface.inversematrix = *inversematrix;
10852         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10853         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10854         R_EntityMatrix(&rsurface.matrix);
10855         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10856         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10857         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10858         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10859         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10860         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10861         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10862         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10863         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10864         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10865         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10866         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10867         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);
10868         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10869         rsurface.frameblend[0].lerp = 1;
10870         rsurface.ent_alttextures = false;
10871         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10872         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10873         if (wanttangents)
10874         {
10875                 rsurface.modelvertex3f = vertex3f;
10876                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10877                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10878                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10879         }
10880         else if (wantnormals)
10881         {
10882                 rsurface.modelvertex3f = vertex3f;
10883                 rsurface.modelsvector3f = NULL;
10884                 rsurface.modeltvector3f = NULL;
10885                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10886         }
10887         else
10888         {
10889                 rsurface.modelvertex3f = vertex3f;
10890                 rsurface.modelsvector3f = NULL;
10891                 rsurface.modeltvector3f = NULL;
10892                 rsurface.modelnormal3f = NULL;
10893         }
10894         rsurface.modelvertexmesh = NULL;
10895         rsurface.modelvertexmeshbuffer = NULL;
10896         rsurface.modelvertexposition = NULL;
10897         rsurface.modelvertexpositionbuffer = NULL;
10898         rsurface.modelvertex3f_vertexbuffer = 0;
10899         rsurface.modelvertex3f_bufferoffset = 0;
10900         rsurface.modelsvector3f_vertexbuffer = 0;
10901         rsurface.modelsvector3f_bufferoffset = 0;
10902         rsurface.modeltvector3f_vertexbuffer = 0;
10903         rsurface.modeltvector3f_bufferoffset = 0;
10904         rsurface.modelnormal3f_vertexbuffer = 0;
10905         rsurface.modelnormal3f_bufferoffset = 0;
10906         rsurface.modelgeneratedvertex = true;
10907         rsurface.modellightmapcolor4f  = color4f;
10908         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10909         rsurface.modellightmapcolor4f_bufferoffset = 0;
10910         rsurface.modeltexcoordtexture2f  = texcoord2f;
10911         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10912         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10913         rsurface.modeltexcoordlightmap2f  = NULL;
10914         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10915         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10916         rsurface.modelelement3i = element3i;
10917         rsurface.modelelement3i_indexbuffer = NULL;
10918         rsurface.modelelement3i_bufferoffset = 0;
10919         rsurface.modelelement3s = element3s;
10920         rsurface.modelelement3s_indexbuffer = NULL;
10921         rsurface.modelelement3s_bufferoffset = 0;
10922         rsurface.modellightmapoffsets = NULL;
10923         rsurface.modelsurfaces = NULL;
10924         rsurface.batchgeneratedvertex = false;
10925         rsurface.batchfirstvertex = 0;
10926         rsurface.batchnumvertices = 0;
10927         rsurface.batchfirsttriangle = 0;
10928         rsurface.batchnumtriangles = 0;
10929         rsurface.batchvertex3f  = NULL;
10930         rsurface.batchvertex3f_vertexbuffer = NULL;
10931         rsurface.batchvertex3f_bufferoffset = 0;
10932         rsurface.batchsvector3f = NULL;
10933         rsurface.batchsvector3f_vertexbuffer = NULL;
10934         rsurface.batchsvector3f_bufferoffset = 0;
10935         rsurface.batchtvector3f = NULL;
10936         rsurface.batchtvector3f_vertexbuffer = NULL;
10937         rsurface.batchtvector3f_bufferoffset = 0;
10938         rsurface.batchnormal3f  = NULL;
10939         rsurface.batchnormal3f_vertexbuffer = NULL;
10940         rsurface.batchnormal3f_bufferoffset = 0;
10941         rsurface.batchlightmapcolor4f = NULL;
10942         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10943         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10944         rsurface.batchtexcoordtexture2f = NULL;
10945         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10946         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10947         rsurface.batchtexcoordlightmap2f = NULL;
10948         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10949         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10950         rsurface.batchvertexmesh = NULL;
10951         rsurface.batchvertexmeshbuffer = NULL;
10952         rsurface.batchvertexposition = NULL;
10953         rsurface.batchvertexpositionbuffer = NULL;
10954         rsurface.batchelement3i = NULL;
10955         rsurface.batchelement3i_indexbuffer = NULL;
10956         rsurface.batchelement3i_bufferoffset = 0;
10957         rsurface.batchelement3s = NULL;
10958         rsurface.batchelement3s_indexbuffer = NULL;
10959         rsurface.batchelement3s_bufferoffset = 0;
10960         rsurface.passcolor4f = NULL;
10961         rsurface.passcolor4f_vertexbuffer = NULL;
10962         rsurface.passcolor4f_bufferoffset = 0;
10963
10964         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10965         {
10966                 if ((wantnormals || wanttangents) && !normal3f)
10967                 {
10968                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10969                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10970                 }
10971                 if (wanttangents && !svector3f)
10972                 {
10973                         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);
10974                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10975                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10976                 }
10977         }
10978
10979         // now convert arrays into vertexmesh structs
10980         for (i = 0;i < numvertices;i++)
10981         {
10982                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10983                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10984                 if (rsurface.modelsvector3f)
10985                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10986                 if (rsurface.modeltvector3f)
10987                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10988                 if (rsurface.modelnormal3f)
10989                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10990                 if (rsurface.modellightmapcolor4f)
10991                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10992                 if (rsurface.modeltexcoordtexture2f)
10993                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10994                 if (rsurface.modeltexcoordlightmap2f)
10995                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10996         }
10997 }
10998
10999 float RSurf_FogPoint(const float *v)
11000 {
11001         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11002         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11003         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11004         float FogHeightFade = r_refdef.fogheightfade;
11005         float fogfrac;
11006         unsigned int fogmasktableindex;
11007         if (r_refdef.fogplaneviewabove)
11008                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11009         else
11010                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11011         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11012         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11013 }
11014
11015 float RSurf_FogVertex(const float *v)
11016 {
11017         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11018         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11019         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11020         float FogHeightFade = rsurface.fogheightfade;
11021         float fogfrac;
11022         unsigned int fogmasktableindex;
11023         if (r_refdef.fogplaneviewabove)
11024                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11025         else
11026                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11027         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11028         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11029 }
11030
11031 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11032 {
11033         int i;
11034         for (i = 0;i < numelements;i++)
11035                 outelement3i[i] = inelement3i[i] + adjust;
11036 }
11037
11038 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11039 extern cvar_t gl_vbo;
11040 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11041 {
11042         int deformindex;
11043         int firsttriangle;
11044         int numtriangles;
11045         int firstvertex;
11046         int endvertex;
11047         int numvertices;
11048         int surfacefirsttriangle;
11049         int surfacenumtriangles;
11050         int surfacefirstvertex;
11051         int surfaceendvertex;
11052         int surfacenumvertices;
11053         int surfaceadjustvertex;
11054         int needsupdate;
11055         int i, j;
11056         qboolean gaps;
11057         qboolean dynamicvertex;
11058         float amplitude;
11059         float animpos;
11060         float scale;
11061         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11062         float waveparms[4];
11063         q3shaderinfo_deform_t *deform;
11064         const msurface_t *surface, *firstsurface;
11065         r_vertexposition_t *vertexposition;
11066         r_vertexmesh_t *vertexmesh;
11067         if (!texturenumsurfaces)
11068                 return;
11069         // find vertex range of this surface batch
11070         gaps = false;
11071         firstsurface = texturesurfacelist[0];
11072         firsttriangle = firstsurface->num_firsttriangle;
11073         numtriangles = 0;
11074         firstvertex = endvertex = firstsurface->num_firstvertex;
11075         for (i = 0;i < texturenumsurfaces;i++)
11076         {
11077                 surface = texturesurfacelist[i];
11078                 if (surface != firstsurface + i)
11079                         gaps = true;
11080                 surfacefirstvertex = surface->num_firstvertex;
11081                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11082                 surfacenumtriangles = surface->num_triangles;
11083                 if (firstvertex > surfacefirstvertex)
11084                         firstvertex = surfacefirstvertex;
11085                 if (endvertex < surfaceendvertex)
11086                         endvertex = surfaceendvertex;
11087                 numtriangles += surfacenumtriangles;
11088         }
11089         if (!numtriangles)
11090                 return;
11091
11092         // we now know the vertex range used, and if there are any gaps in it
11093         rsurface.batchfirstvertex = firstvertex;
11094         rsurface.batchnumvertices = endvertex - firstvertex;
11095         rsurface.batchfirsttriangle = firsttriangle;
11096         rsurface.batchnumtriangles = numtriangles;
11097
11098         // this variable holds flags for which properties have been updated that
11099         // may require regenerating vertexmesh or vertexposition arrays...
11100         needsupdate = 0;
11101
11102         // check if any dynamic vertex processing must occur
11103         dynamicvertex = false;
11104
11105         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11106                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11107         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11108         {
11109                 switch (deform->deform)
11110                 {
11111                 default:
11112                 case Q3DEFORM_PROJECTIONSHADOW:
11113                 case Q3DEFORM_TEXT0:
11114                 case Q3DEFORM_TEXT1:
11115                 case Q3DEFORM_TEXT2:
11116                 case Q3DEFORM_TEXT3:
11117                 case Q3DEFORM_TEXT4:
11118                 case Q3DEFORM_TEXT5:
11119                 case Q3DEFORM_TEXT6:
11120                 case Q3DEFORM_TEXT7:
11121                 case Q3DEFORM_NONE:
11122                         break;
11123                 case Q3DEFORM_AUTOSPRITE:
11124                         dynamicvertex = true;
11125                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11126                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11127                         break;
11128                 case Q3DEFORM_AUTOSPRITE2:
11129                         dynamicvertex = true;
11130                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11131                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11132                         break;
11133                 case Q3DEFORM_NORMAL:
11134                         dynamicvertex = true;
11135                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11136                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11137                         break;
11138                 case Q3DEFORM_WAVE:
11139                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11140                                 break; // if wavefunc is a nop, ignore this transform
11141                         dynamicvertex = true;
11142                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11143                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11144                         break;
11145                 case Q3DEFORM_BULGE:
11146                         dynamicvertex = true;
11147                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11148                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11149                         break;
11150                 case Q3DEFORM_MOVE:
11151                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11152                                 break; // if wavefunc is a nop, ignore this transform
11153                         dynamicvertex = true;
11154                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11155                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11156                         break;
11157                 }
11158         }
11159         switch(rsurface.texture->tcgen.tcgen)
11160         {
11161         default:
11162         case Q3TCGEN_TEXTURE:
11163                 break;
11164         case Q3TCGEN_LIGHTMAP:
11165                 dynamicvertex = true;
11166                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11167                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11168                 break;
11169         case Q3TCGEN_VECTOR:
11170                 dynamicvertex = true;
11171                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11172                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11173                 break;
11174         case Q3TCGEN_ENVIRONMENT:
11175                 dynamicvertex = true;
11176                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11177                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11178                 break;
11179         }
11180         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11181         {
11182                 dynamicvertex = true;
11183                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11184                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11185         }
11186
11187         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11188         {
11189                 dynamicvertex = true;
11190                 batchneed |= BATCHNEED_NOGAPS;
11191                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11192         }
11193
11194         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11195         {
11196                 dynamicvertex = true;
11197                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11198                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11199         }
11200
11201         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11202         {
11203                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11204                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11205                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11206                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11207                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11208                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11209                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11210         }
11211
11212         // when the model data has no vertex buffer (dynamic mesh), we need to
11213         // eliminate gaps
11214         if (!rsurface.modelvertexmeshbuffer)
11215                 batchneed |= BATCHNEED_NOGAPS;
11216
11217         // if needsupdate, we have to do a dynamic vertex batch for sure
11218         if (needsupdate & batchneed)
11219                 dynamicvertex = true;
11220
11221         // see if we need to build vertexmesh from arrays
11222         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11223                 dynamicvertex = true;
11224
11225         // see if we need to build vertexposition from arrays
11226         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11227                 dynamicvertex = true;
11228
11229         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11230         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11231                 dynamicvertex = true;
11232
11233         // if there is a chance of animated vertex colors, it's a dynamic batch
11234         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11235                 dynamicvertex = true;
11236
11237         rsurface.batchvertex3f = rsurface.modelvertex3f;
11238         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11239         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11240         rsurface.batchsvector3f = rsurface.modelsvector3f;
11241         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11242         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11243         rsurface.batchtvector3f = rsurface.modeltvector3f;
11244         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11245         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11246         rsurface.batchnormal3f = rsurface.modelnormal3f;
11247         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11248         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11249         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11250         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11251         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11252         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11253         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11254         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11255         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11256         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11257         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11258         rsurface.batchvertexposition = rsurface.modelvertexposition;
11259         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11260         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11261         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11262         rsurface.batchelement3i = rsurface.modelelement3i;
11263         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11264         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11265         rsurface.batchelement3s = rsurface.modelelement3s;
11266         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11267         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11268
11269         // if any dynamic vertex processing has to occur in software, we copy the
11270         // entire surface list together before processing to rebase the vertices
11271         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11272         //
11273         // if any gaps exist and we do not have a static vertex buffer, we have to
11274         // copy the surface list together to avoid wasting upload bandwidth on the
11275         // vertices in the gaps.
11276         //
11277         // if gaps exist and we have a static vertex buffer, we still have to
11278         // combine the index buffer ranges into one dynamic index buffer.
11279         //
11280         // in all cases we end up with data that can be drawn in one call.
11281
11282         if (!dynamicvertex)
11283         {
11284                 // static vertex data, just set pointers...
11285                 rsurface.batchgeneratedvertex = false;
11286                 // if there are gaps, we want to build a combined index buffer,
11287                 // otherwise use the original static buffer with an appropriate offset
11288                 if (gaps)
11289                 {
11290                         firsttriangle = 0;
11291                         numtriangles = 0;
11292                         for (i = 0;i < texturenumsurfaces;i++)
11293                         {
11294                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11295                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11296                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11297                                 numtriangles += surfacenumtriangles;
11298                         }
11299                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11300                         rsurface.batchelement3i_indexbuffer = NULL;
11301                         rsurface.batchelement3i_bufferoffset = 0;
11302                         rsurface.batchelement3s = NULL;
11303                         rsurface.batchelement3s_indexbuffer = NULL;
11304                         rsurface.batchelement3s_bufferoffset = 0;
11305                         if (endvertex <= 65536)
11306                         {
11307                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11308                                 for (i = 0;i < numtriangles*3;i++)
11309                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11310                         }
11311                         rsurface.batchfirsttriangle = firsttriangle;
11312                         rsurface.batchnumtriangles = numtriangles;
11313                 }
11314                 return;
11315         }
11316
11317         // something needs software processing, do it for real...
11318         // we only directly handle interleaved array data in this case...
11319         rsurface.batchgeneratedvertex = true;
11320
11321         // now copy the vertex data into a combined array and make an index array
11322         // (this is what Quake3 does all the time)
11323         //if (gaps || rsurface.batchfirstvertex)
11324         {
11325                 rsurface.batchvertexposition = NULL;
11326                 rsurface.batchvertexpositionbuffer = NULL;
11327                 rsurface.batchvertexmesh = NULL;
11328                 rsurface.batchvertexmeshbuffer = NULL;
11329                 rsurface.batchvertex3f = NULL;
11330                 rsurface.batchvertex3f_vertexbuffer = NULL;
11331                 rsurface.batchvertex3f_bufferoffset = 0;
11332                 rsurface.batchsvector3f = NULL;
11333                 rsurface.batchsvector3f_vertexbuffer = NULL;
11334                 rsurface.batchsvector3f_bufferoffset = 0;
11335                 rsurface.batchtvector3f = NULL;
11336                 rsurface.batchtvector3f_vertexbuffer = NULL;
11337                 rsurface.batchtvector3f_bufferoffset = 0;
11338                 rsurface.batchnormal3f = NULL;
11339                 rsurface.batchnormal3f_vertexbuffer = NULL;
11340                 rsurface.batchnormal3f_bufferoffset = 0;
11341                 rsurface.batchlightmapcolor4f = NULL;
11342                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11343                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11344                 rsurface.batchtexcoordtexture2f = NULL;
11345                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11346                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11347                 rsurface.batchtexcoordlightmap2f = NULL;
11348                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11349                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11350                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11351                 rsurface.batchelement3i_indexbuffer = NULL;
11352                 rsurface.batchelement3i_bufferoffset = 0;
11353                 rsurface.batchelement3s = NULL;
11354                 rsurface.batchelement3s_indexbuffer = NULL;
11355                 rsurface.batchelement3s_bufferoffset = 0;
11356                 // we'll only be setting up certain arrays as needed
11357                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11358                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11359                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11360                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11361                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11362                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11363                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11364                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11365                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11366                 {
11367                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11368                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11369                 }
11370                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11371                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11372                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11373                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11374                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11375                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11376                 numvertices = 0;
11377                 numtriangles = 0;
11378                 for (i = 0;i < texturenumsurfaces;i++)
11379                 {
11380                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11381                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11382                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11383                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11384                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11385                         // copy only the data requested
11386                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11387                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11388                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11389                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11390                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11391                         {
11392                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11393                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11394                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11395                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11396                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11397                                 {
11398                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11399                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11400                                 }
11401                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11402                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11403                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11404                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11405                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11406                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11407                         }
11408                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11409                         numvertices += surfacenumvertices;
11410                         numtriangles += surfacenumtriangles;
11411                 }
11412
11413                 // generate a 16bit index array as well if possible
11414                 // (in general, dynamic batches fit)
11415                 if (numvertices <= 65536)
11416                 {
11417                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11418                         for (i = 0;i < numtriangles*3;i++)
11419                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11420                 }
11421
11422                 // since we've copied everything, the batch now starts at 0
11423                 rsurface.batchfirstvertex = 0;
11424                 rsurface.batchnumvertices = numvertices;
11425                 rsurface.batchfirsttriangle = 0;
11426                 rsurface.batchnumtriangles = numtriangles;
11427         }
11428
11429         // q1bsp surfaces rendered in vertex color mode have to have colors
11430         // calculated based on lightstyles
11431         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11432         {
11433                 // generate color arrays for the surfaces in this list
11434                 int c[4];
11435                 int scale;
11436                 int size3;
11437                 const int *offsets;
11438                 const unsigned char *lm;
11439                 numvertices = 0;
11440                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11441                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11442                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11443                 for (i = 0;i < texturenumsurfaces;i++)
11444                 {
11445                         surface = texturesurfacelist[i];
11446                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11447                         surfacenumvertices = surface->num_vertices;
11448                         if (surface->lightmapinfo->samples)
11449                         {
11450                                 for (j = 0;j < surfacenumvertices;j++)
11451                                 {
11452                                         lm = surface->lightmapinfo->samples + offsets[j];
11453                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11454                                         VectorScale(lm, scale, c);
11455                                         if (surface->lightmapinfo->styles[1] != 255)
11456                                         {
11457                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11458                                                 lm += size3;
11459                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11460                                                 VectorMA(c, scale, lm, c);
11461                                                 if (surface->lightmapinfo->styles[2] != 255)
11462                                                 {
11463                                                         lm += size3;
11464                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11465                                                         VectorMA(c, scale, lm, c);
11466                                                         if (surface->lightmapinfo->styles[3] != 255)
11467                                                         {
11468                                                                 lm += size3;
11469                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11470                                                                 VectorMA(c, scale, lm, c);
11471                                                         }
11472                                                 }
11473                                         }
11474                                         c[0] >>= 15;
11475                                         c[1] >>= 15;
11476                                         c[2] >>= 15;
11477                                         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);
11478                                         numvertices++;
11479                                 }
11480                         }
11481                         else
11482                         {
11483                                 for (j = 0;j < surfacenumvertices;j++)
11484                                 {
11485                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11486                                         numvertices++;
11487                                 }
11488                         }
11489                 }
11490         }
11491
11492         // if vertices are deformed (sprite flares and things in maps, possibly
11493         // water waves, bulges and other deformations), modify the copied vertices
11494         // in place
11495         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11496         {
11497                 switch (deform->deform)
11498                 {
11499                 default:
11500                 case Q3DEFORM_PROJECTIONSHADOW:
11501                 case Q3DEFORM_TEXT0:
11502                 case Q3DEFORM_TEXT1:
11503                 case Q3DEFORM_TEXT2:
11504                 case Q3DEFORM_TEXT3:
11505                 case Q3DEFORM_TEXT4:
11506                 case Q3DEFORM_TEXT5:
11507                 case Q3DEFORM_TEXT6:
11508                 case Q3DEFORM_TEXT7:
11509                 case Q3DEFORM_NONE:
11510                         break;
11511                 case Q3DEFORM_AUTOSPRITE:
11512                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11513                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11514                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11515                         VectorNormalize(newforward);
11516                         VectorNormalize(newright);
11517                         VectorNormalize(newup);
11518                         // a single autosprite surface can contain multiple sprites...
11519                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11520                         {
11521                                 VectorClear(center);
11522                                 for (i = 0;i < 4;i++)
11523                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11524                                 VectorScale(center, 0.25f, center);
11525                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11526                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11527                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11528                                 for (i = 0;i < 4;i++)
11529                                 {
11530                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11531                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11532                                 }
11533                         }
11534                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11535                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11536                         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);
11537                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11538                         rsurface.batchvertex3f_vertexbuffer = NULL;
11539                         rsurface.batchvertex3f_bufferoffset = 0;
11540                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11541                         rsurface.batchsvector3f_vertexbuffer = NULL;
11542                         rsurface.batchsvector3f_bufferoffset = 0;
11543                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11544                         rsurface.batchtvector3f_vertexbuffer = NULL;
11545                         rsurface.batchtvector3f_bufferoffset = 0;
11546                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11547                         rsurface.batchnormal3f_vertexbuffer = NULL;
11548                         rsurface.batchnormal3f_bufferoffset = 0;
11549                         break;
11550                 case Q3DEFORM_AUTOSPRITE2:
11551                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11552                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11553                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11554                         VectorNormalize(newforward);
11555                         VectorNormalize(newright);
11556                         VectorNormalize(newup);
11557                         {
11558                                 const float *v1, *v2;
11559                                 vec3_t start, end;
11560                                 float f, l;
11561                                 struct
11562                                 {
11563                                         float length2;
11564                                         const float *v1;
11565                                         const float *v2;
11566                                 }
11567                                 shortest[2];
11568                                 memset(shortest, 0, sizeof(shortest));
11569                                 // a single autosprite surface can contain multiple sprites...
11570                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11571                                 {
11572                                         VectorClear(center);
11573                                         for (i = 0;i < 4;i++)
11574                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11575                                         VectorScale(center, 0.25f, center);
11576                                         // find the two shortest edges, then use them to define the
11577                                         // axis vectors for rotating around the central axis
11578                                         for (i = 0;i < 6;i++)
11579                                         {
11580                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11581                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11582                                                 l = VectorDistance2(v1, v2);
11583                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11584                                                 if (v1[2] != v2[2])
11585                                                         l += (1.0f / 1024.0f);
11586                                                 if (shortest[0].length2 > l || i == 0)
11587                                                 {
11588                                                         shortest[1] = shortest[0];
11589                                                         shortest[0].length2 = l;
11590                                                         shortest[0].v1 = v1;
11591                                                         shortest[0].v2 = v2;
11592                                                 }
11593                                                 else if (shortest[1].length2 > l || i == 1)
11594                                                 {
11595                                                         shortest[1].length2 = l;
11596                                                         shortest[1].v1 = v1;
11597                                                         shortest[1].v2 = v2;
11598                                                 }
11599                                         }
11600                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11601                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11602                                         // this calculates the right vector from the shortest edge
11603                                         // and the up vector from the edge midpoints
11604                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11605                                         VectorNormalize(right);
11606                                         VectorSubtract(end, start, up);
11607                                         VectorNormalize(up);
11608                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11609                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11610                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11611                                         VectorNegate(forward, forward);
11612                                         VectorReflect(forward, 0, up, forward);
11613                                         VectorNormalize(forward);
11614                                         CrossProduct(up, forward, newright);
11615                                         VectorNormalize(newright);
11616                                         // rotate the quad around the up axis vector, this is made
11617                                         // especially easy by the fact we know the quad is flat,
11618                                         // so we only have to subtract the center position and
11619                                         // measure distance along the right vector, and then
11620                                         // multiply that by the newright vector and add back the
11621                                         // center position
11622                                         // we also need to subtract the old position to undo the
11623                                         // displacement from the center, which we do with a
11624                                         // DotProduct, the subtraction/addition of center is also
11625                                         // optimized into DotProducts here
11626                                         l = DotProduct(right, center);
11627                                         for (i = 0;i < 4;i++)
11628                                         {
11629                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11630                                                 f = DotProduct(right, v1) - l;
11631                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11632                                         }
11633                                 }
11634                         }
11635                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11636                         rsurface.batchvertex3f_vertexbuffer = NULL;
11637                         rsurface.batchvertex3f_bufferoffset = 0;
11638                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11639                         {
11640                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11641                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11642                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11643                                 rsurface.batchnormal3f_bufferoffset = 0;
11644                         }
11645                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11646                         {
11647                                 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);
11648                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11649                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11650                                 rsurface.batchsvector3f_bufferoffset = 0;
11651                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11652                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11653                                 rsurface.batchtvector3f_bufferoffset = 0;
11654                         }
11655                         break;
11656                 case Q3DEFORM_NORMAL:
11657                         // deform the normals to make reflections wavey
11658                         for (j = 0;j < rsurface.batchnumvertices;j++)
11659                         {
11660                                 float vertex[3];
11661                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11662                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11663                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11664                                 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]);
11665                                 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]);
11666                                 VectorNormalize(normal);
11667                         }
11668                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11669                         rsurface.batchnormal3f_vertexbuffer = NULL;
11670                         rsurface.batchnormal3f_bufferoffset = 0;
11671                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11672                         {
11673                                 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);
11674                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11675                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11676                                 rsurface.batchsvector3f_bufferoffset = 0;
11677                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11678                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11679                                 rsurface.batchtvector3f_bufferoffset = 0;
11680                         }
11681                         break;
11682                 case Q3DEFORM_WAVE:
11683                         // deform vertex array to make wavey water and flags and such
11684                         waveparms[0] = deform->waveparms[0];
11685                         waveparms[1] = deform->waveparms[1];
11686                         waveparms[2] = deform->waveparms[2];
11687                         waveparms[3] = deform->waveparms[3];
11688                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11689                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11690                         // this is how a divisor of vertex influence on deformation
11691                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11692                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11693                         for (j = 0;j < rsurface.batchnumvertices;j++)
11694                         {
11695                                 // if the wavefunc depends on time, evaluate it per-vertex
11696                                 if (waveparms[3])
11697                                 {
11698                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11699                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11700                                 }
11701                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11702                         }
11703                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11704                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11705                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11706                         rsurface.batchvertex3f_vertexbuffer = NULL;
11707                         rsurface.batchvertex3f_bufferoffset = 0;
11708                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11709                         rsurface.batchnormal3f_vertexbuffer = NULL;
11710                         rsurface.batchnormal3f_bufferoffset = 0;
11711                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11712                         {
11713                                 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);
11714                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11715                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11716                                 rsurface.batchsvector3f_bufferoffset = 0;
11717                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11718                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11719                                 rsurface.batchtvector3f_bufferoffset = 0;
11720                         }
11721                         break;
11722                 case Q3DEFORM_BULGE:
11723                         // deform vertex array to make the surface have moving bulges
11724                         for (j = 0;j < rsurface.batchnumvertices;j++)
11725                         {
11726                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11727                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11728                         }
11729                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11730                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11731                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11732                         rsurface.batchvertex3f_vertexbuffer = NULL;
11733                         rsurface.batchvertex3f_bufferoffset = 0;
11734                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11735                         rsurface.batchnormal3f_vertexbuffer = NULL;
11736                         rsurface.batchnormal3f_bufferoffset = 0;
11737                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11738                         {
11739                                 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);
11740                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11741                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11742                                 rsurface.batchsvector3f_bufferoffset = 0;
11743                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11744                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11745                                 rsurface.batchtvector3f_bufferoffset = 0;
11746                         }
11747                         break;
11748                 case Q3DEFORM_MOVE:
11749                         // deform vertex array
11750                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11751                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11752                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11753                         VectorScale(deform->parms, scale, waveparms);
11754                         for (j = 0;j < rsurface.batchnumvertices;j++)
11755                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11756                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11757                         rsurface.batchvertex3f_vertexbuffer = NULL;
11758                         rsurface.batchvertex3f_bufferoffset = 0;
11759                         break;
11760                 }
11761         }
11762
11763         // generate texcoords based on the chosen texcoord source
11764         switch(rsurface.texture->tcgen.tcgen)
11765         {
11766         default:
11767         case Q3TCGEN_TEXTURE:
11768                 break;
11769         case Q3TCGEN_LIGHTMAP:
11770                 if (rsurface.batchtexcoordlightmap2f)
11771                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11772                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11773                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11774                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11775                 break;
11776         case Q3TCGEN_VECTOR:
11777                 for (j = 0;j < rsurface.batchnumvertices;j++)
11778                 {
11779                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11780                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11781                 }
11782                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11783                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11784                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11785                 break;
11786         case Q3TCGEN_ENVIRONMENT:
11787                 // make environment reflections using a spheremap
11788                 for (j = 0;j < rsurface.batchnumvertices;j++)
11789                 {
11790                         // identical to Q3A's method, but executed in worldspace so
11791                         // carried models can be shiny too
11792
11793                         float viewer[3], d, reflected[3], worldreflected[3];
11794
11795                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11796                         // VectorNormalize(viewer);
11797
11798                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11799
11800                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11801                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11802                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11803                         // note: this is proportinal to viewer, so we can normalize later
11804
11805                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11806                         VectorNormalize(worldreflected);
11807
11808                         // note: this sphere map only uses world x and z!
11809                         // so positive and negative y will LOOK THE SAME.
11810                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11811                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11812                 }
11813                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11814                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11815                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11816                 break;
11817         }
11818         // the only tcmod that needs software vertex processing is turbulent, so
11819         // check for it here and apply the changes if needed
11820         // and we only support that as the first one
11821         // (handling a mixture of turbulent and other tcmods would be problematic
11822         //  without punting it entirely to a software path)
11823         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11824         {
11825                 amplitude = rsurface.texture->tcmods[0].parms[1];
11826                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11827                 for (j = 0;j < rsurface.batchnumvertices;j++)
11828                 {
11829                         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);
11830                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11831                 }
11832                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11833                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11834                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11835         }
11836
11837         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11838         {
11839                 // convert the modified arrays to vertex structs
11840                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11841                 rsurface.batchvertexmeshbuffer = NULL;
11842                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11843                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11844                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11845                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11846                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11847                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11848                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11849                 {
11850                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11851                         {
11852                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11853                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11854                         }
11855                 }
11856                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11857                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11858                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11859                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11860                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11861                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11862                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11863                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11864                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11865         }
11866
11867         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11868         {
11869                 // convert the modified arrays to vertex structs
11870                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11871                 rsurface.batchvertexpositionbuffer = NULL;
11872                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11873                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11874                 else
11875                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11876                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11877         }
11878 }
11879
11880 void RSurf_DrawBatch(void)
11881 {
11882         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);
11883 }
11884
11885 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11886 {
11887         // pick the closest matching water plane
11888         int planeindex, vertexindex, bestplaneindex = -1;
11889         float d, bestd;
11890         vec3_t vert;
11891         const float *v;
11892         r_waterstate_waterplane_t *p;
11893         bestd = 0;
11894         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11895         {
11896                 if(p->camera_entity != rsurface.texture->camera_entity)
11897                         continue;
11898                 d = 0;
11899                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11900                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11901                 {
11902                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11903                         d += fabs(PlaneDiff(vert, &p->plane));
11904                 }
11905                 if (bestd > d || bestplaneindex < 0)
11906                 {
11907                         bestd = d;
11908                         bestplaneindex = planeindex;
11909                 }
11910         }
11911         return bestplaneindex;
11912 }
11913
11914 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11915 {
11916         int i;
11917         for (i = 0;i < rsurface.batchnumvertices;i++)
11918                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11919         rsurface.passcolor4f = rsurface.array_passcolor4f;
11920         rsurface.passcolor4f_vertexbuffer = 0;
11921         rsurface.passcolor4f_bufferoffset = 0;
11922 }
11923
11924 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11925 {
11926         int i;
11927         float f;
11928         const float *v;
11929         const float *c;
11930         float *c2;
11931         if (rsurface.passcolor4f)
11932         {
11933                 // generate color arrays
11934                 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)
11935                 {
11936                         f = RSurf_FogVertex(v);
11937                         c2[0] = c[0] * f;
11938                         c2[1] = c[1] * f;
11939                         c2[2] = c[2] * f;
11940                         c2[3] = c[3];
11941                 }
11942         }
11943         else
11944         {
11945                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11946                 {
11947                         f = RSurf_FogVertex(v);
11948                         c2[0] = f;
11949                         c2[1] = f;
11950                         c2[2] = f;
11951                         c2[3] = 1;
11952                 }
11953         }
11954         rsurface.passcolor4f = rsurface.array_passcolor4f;
11955         rsurface.passcolor4f_vertexbuffer = 0;
11956         rsurface.passcolor4f_bufferoffset = 0;
11957 }
11958
11959 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11960 {
11961         int i;
11962         float f;
11963         const float *v;
11964         const float *c;
11965         float *c2;
11966         if (!rsurface.passcolor4f)
11967                 return;
11968         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)
11969         {
11970                 f = RSurf_FogVertex(v);
11971                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11972                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11973                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11974                 c2[3] = c[3];
11975         }
11976         rsurface.passcolor4f = rsurface.array_passcolor4f;
11977         rsurface.passcolor4f_vertexbuffer = 0;
11978         rsurface.passcolor4f_bufferoffset = 0;
11979 }
11980
11981 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11982 {
11983         int i;
11984         const float *c;
11985         float *c2;
11986         if (!rsurface.passcolor4f)
11987                 return;
11988         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11989         {
11990                 c2[0] = c[0] * r;
11991                 c2[1] = c[1] * g;
11992                 c2[2] = c[2] * b;
11993                 c2[3] = c[3] * a;
11994         }
11995         rsurface.passcolor4f = rsurface.array_passcolor4f;
11996         rsurface.passcolor4f_vertexbuffer = 0;
11997         rsurface.passcolor4f_bufferoffset = 0;
11998 }
11999
12000 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12001 {
12002         int i;
12003         const float *c;
12004         float *c2;
12005         if (!rsurface.passcolor4f)
12006                 return;
12007         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12008         {
12009                 c2[0] = c[0] + r_refdef.scene.ambient;
12010                 c2[1] = c[1] + r_refdef.scene.ambient;
12011                 c2[2] = c[2] + r_refdef.scene.ambient;
12012                 c2[3] = c[3];
12013         }
12014         rsurface.passcolor4f = rsurface.array_passcolor4f;
12015         rsurface.passcolor4f_vertexbuffer = 0;
12016         rsurface.passcolor4f_bufferoffset = 0;
12017 }
12018
12019 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12020 {
12021         // TODO: optimize
12022         rsurface.passcolor4f = NULL;
12023         rsurface.passcolor4f_vertexbuffer = 0;
12024         rsurface.passcolor4f_bufferoffset = 0;
12025         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12026         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12027         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12028         GL_Color(r, g, b, a);
12029         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12030         RSurf_DrawBatch();
12031 }
12032
12033 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12034 {
12035         // TODO: optimize applyfog && applycolor case
12036         // just apply fog if necessary, and tint the fog color array if necessary
12037         rsurface.passcolor4f = NULL;
12038         rsurface.passcolor4f_vertexbuffer = 0;
12039         rsurface.passcolor4f_bufferoffset = 0;
12040         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12041         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12042         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12043         GL_Color(r, g, b, a);
12044         RSurf_DrawBatch();
12045 }
12046
12047 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12048 {
12049         // TODO: optimize
12050         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12051         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12052         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12053         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12054         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12055         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12056         GL_Color(r, g, b, a);
12057         RSurf_DrawBatch();
12058 }
12059
12060 static void RSurf_DrawBatch_GL11_ClampColor(void)
12061 {
12062         int i;
12063         const float *c1;
12064         float *c2;
12065         if (!rsurface.passcolor4f)
12066                 return;
12067         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12068         {
12069                 c2[0] = bound(0.0f, c1[0], 1.0f);
12070                 c2[1] = bound(0.0f, c1[1], 1.0f);
12071                 c2[2] = bound(0.0f, c1[2], 1.0f);
12072                 c2[3] = bound(0.0f, c1[3], 1.0f);
12073         }
12074 }
12075
12076 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12077 {
12078         int i;
12079         float f;
12080         float alpha;
12081         const float *v;
12082         const float *n;
12083         float *c;
12084         vec3_t ambientcolor;
12085         vec3_t diffusecolor;
12086         vec3_t lightdir;
12087         // TODO: optimize
12088         // model lighting
12089         VectorCopy(rsurface.modellight_lightdir, lightdir);
12090         f = 0.5f * r_refdef.lightmapintensity;
12091         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12092         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12093         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12094         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12095         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12096         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12097         alpha = *a;
12098         if (VectorLength2(diffusecolor) > 0)
12099         {
12100                 // q3-style directional shading
12101                 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)
12102                 {
12103                         if ((f = DotProduct(n, lightdir)) > 0)
12104                                 VectorMA(ambientcolor, f, diffusecolor, c);
12105                         else
12106                                 VectorCopy(ambientcolor, c);
12107                         c[3] = alpha;
12108                 }
12109                 *r = 1;
12110                 *g = 1;
12111                 *b = 1;
12112                 *a = 1;
12113                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12114                 rsurface.passcolor4f_vertexbuffer = 0;
12115                 rsurface.passcolor4f_bufferoffset = 0;
12116                 *applycolor = false;
12117         }
12118         else
12119         {
12120                 *r = ambientcolor[0];
12121                 *g = ambientcolor[1];
12122                 *b = ambientcolor[2];
12123                 rsurface.passcolor4f = NULL;
12124                 rsurface.passcolor4f_vertexbuffer = 0;
12125                 rsurface.passcolor4f_bufferoffset = 0;
12126         }
12127 }
12128
12129 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12130 {
12131         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12132         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12133         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12134         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12135         GL_Color(r, g, b, a);
12136         RSurf_DrawBatch();
12137 }
12138
12139 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12140 {
12141         int i;
12142         float f;
12143         const float *v;
12144         float *c;
12145         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12146         {
12147                 f = 1 - RSurf_FogVertex(v);
12148                 c[0] = r;
12149                 c[1] = g;
12150                 c[2] = b;
12151                 c[3] = f * a;
12152         }
12153 }
12154
12155 void RSurf_SetupDepthAndCulling(void)
12156 {
12157         // submodels are biased to avoid z-fighting with world surfaces that they
12158         // may be exactly overlapping (avoids z-fighting artifacts on certain
12159         // doors and things in Quake maps)
12160         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12161         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12162         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12163         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12164 }
12165
12166 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12167 {
12168         // transparent sky would be ridiculous
12169         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12170                 return;
12171         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12172         skyrenderlater = true;
12173         RSurf_SetupDepthAndCulling();
12174         GL_DepthMask(true);
12175         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12176         // skymasking on them, and Quake3 never did sky masking (unlike
12177         // software Quake and software Quake2), so disable the sky masking
12178         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12179         // and skymasking also looks very bad when noclipping outside the
12180         // level, so don't use it then either.
12181         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12182         {
12183                 R_Mesh_ResetTextureState();
12184                 if (skyrendermasked)
12185                 {
12186                         R_SetupShader_DepthOrShadow();
12187                         // depth-only (masking)
12188                         GL_ColorMask(0,0,0,0);
12189                         // just to make sure that braindead drivers don't draw
12190                         // anything despite that colormask...
12191                         GL_BlendFunc(GL_ZERO, GL_ONE);
12192                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12193                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12194                 }
12195                 else
12196                 {
12197                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12198                         // fog sky
12199                         GL_BlendFunc(GL_ONE, GL_ZERO);
12200                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12201                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12202                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12203                 }
12204                 RSurf_DrawBatch();
12205                 if (skyrendermasked)
12206                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12207         }
12208         R_Mesh_ResetTextureState();
12209         GL_Color(1, 1, 1, 1);
12210 }
12211
12212 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12213 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12214 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12215 {
12216         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12217                 return;
12218         if (prepass)
12219         {
12220                 // render screenspace normalmap to texture
12221                 GL_DepthMask(true);
12222                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12223                 RSurf_DrawBatch();
12224                 return;
12225         }
12226
12227         // bind lightmap texture
12228
12229         // water/refraction/reflection/camera surfaces have to be handled specially
12230         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12231         {
12232                 int start, end, startplaneindex;
12233                 for (start = 0;start < texturenumsurfaces;start = end)
12234                 {
12235                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12236                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12237                                 ;
12238                         // now that we have a batch using the same planeindex, render it
12239                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12240                         {
12241                                 // render water or distortion background
12242                                 GL_DepthMask(true);
12243                                 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));
12244                                 RSurf_DrawBatch();
12245                                 // blend surface on top
12246                                 GL_DepthMask(false);
12247                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12248                                 RSurf_DrawBatch();
12249                         }
12250                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12251                         {
12252                                 // render surface with reflection texture as input
12253                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12254                                 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));
12255                                 RSurf_DrawBatch();
12256                         }
12257                 }
12258                 return;
12259         }
12260
12261         // render surface batch normally
12262         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12263         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12264         RSurf_DrawBatch();
12265 }
12266
12267 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12268 {
12269         // OpenGL 1.3 path - anything not completely ancient
12270         qboolean applycolor;
12271         qboolean applyfog;
12272         int layerindex;
12273         const texturelayer_t *layer;
12274         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);
12275         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12276
12277         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12278         {
12279                 vec4_t layercolor;
12280                 int layertexrgbscale;
12281                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12282                 {
12283                         if (layerindex == 0)
12284                                 GL_AlphaTest(true);
12285                         else
12286                         {
12287                                 GL_AlphaTest(false);
12288                                 GL_DepthFunc(GL_EQUAL);
12289                         }
12290                 }
12291                 GL_DepthMask(layer->depthmask && writedepth);
12292                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12293                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12294                 {
12295                         layertexrgbscale = 4;
12296                         VectorScale(layer->color, 0.25f, layercolor);
12297                 }
12298                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12299                 {
12300                         layertexrgbscale = 2;
12301                         VectorScale(layer->color, 0.5f, layercolor);
12302                 }
12303                 else
12304                 {
12305                         layertexrgbscale = 1;
12306                         VectorScale(layer->color, 1.0f, layercolor);
12307                 }
12308                 layercolor[3] = layer->color[3];
12309                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12310                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12311                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12312                 switch (layer->type)
12313                 {
12314                 case TEXTURELAYERTYPE_LITTEXTURE:
12315                         // single-pass lightmapped texture with 2x rgbscale
12316                         R_Mesh_TexBind(0, r_texture_white);
12317                         R_Mesh_TexMatrix(0, NULL);
12318                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12319                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12320                         R_Mesh_TexBind(1, layer->texture);
12321                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12322                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12323                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12324                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12325                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12326                         else if (rsurface.uselightmaptexture)
12327                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12328                         else
12329                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12330                         break;
12331                 case TEXTURELAYERTYPE_TEXTURE:
12332                         // singletexture unlit texture with transparency support
12333                         R_Mesh_TexBind(0, layer->texture);
12334                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12335                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12336                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12337                         R_Mesh_TexBind(1, 0);
12338                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12339                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12340                         break;
12341                 case TEXTURELAYERTYPE_FOG:
12342                         // singletexture fogging
12343                         if (layer->texture)
12344                         {
12345                                 R_Mesh_TexBind(0, layer->texture);
12346                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12347                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12348                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12349                         }
12350                         else
12351                         {
12352                                 R_Mesh_TexBind(0, 0);
12353                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12354                         }
12355                         R_Mesh_TexBind(1, 0);
12356                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12357                         // generate a color array for the fog pass
12358                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12359                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12360                         RSurf_DrawBatch();
12361                         break;
12362                 default:
12363                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12364                 }
12365         }
12366         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12367         {
12368                 GL_DepthFunc(GL_LEQUAL);
12369                 GL_AlphaTest(false);
12370         }
12371 }
12372
12373 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12374 {
12375         // OpenGL 1.1 - crusty old voodoo path
12376         qboolean applyfog;
12377         int layerindex;
12378         const texturelayer_t *layer;
12379         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);
12380         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12381
12382         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12383         {
12384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12385                 {
12386                         if (layerindex == 0)
12387                                 GL_AlphaTest(true);
12388                         else
12389                         {
12390                                 GL_AlphaTest(false);
12391                                 GL_DepthFunc(GL_EQUAL);
12392                         }
12393                 }
12394                 GL_DepthMask(layer->depthmask && writedepth);
12395                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12396                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12397                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12398                 switch (layer->type)
12399                 {
12400                 case TEXTURELAYERTYPE_LITTEXTURE:
12401                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12402                         {
12403                                 // two-pass lit texture with 2x rgbscale
12404                                 // first the lightmap pass
12405                                 R_Mesh_TexBind(0, r_texture_white);
12406                                 R_Mesh_TexMatrix(0, NULL);
12407                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12408                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12409                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12410                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12411                                 else if (rsurface.uselightmaptexture)
12412                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12413                                 else
12414                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12415                                 // then apply the texture to it
12416                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12417                                 R_Mesh_TexBind(0, layer->texture);
12418                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12419                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12420                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12421                                 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);
12422                         }
12423                         else
12424                         {
12425                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12426                                 R_Mesh_TexBind(0, layer->texture);
12427                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12428                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12429                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12430                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12431                                         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);
12432                                 else
12433                                         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);
12434                         }
12435                         break;
12436                 case TEXTURELAYERTYPE_TEXTURE:
12437                         // singletexture unlit texture with transparency support
12438                         R_Mesh_TexBind(0, layer->texture);
12439                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12440                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12441                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12442                         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);
12443                         break;
12444                 case TEXTURELAYERTYPE_FOG:
12445                         // singletexture fogging
12446                         if (layer->texture)
12447                         {
12448                                 R_Mesh_TexBind(0, layer->texture);
12449                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12450                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12451                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12452                         }
12453                         else
12454                         {
12455                                 R_Mesh_TexBind(0, 0);
12456                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12457                         }
12458                         // generate a color array for the fog pass
12459                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12460                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12461                         RSurf_DrawBatch();
12462                         break;
12463                 default:
12464                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12465                 }
12466         }
12467         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12468         {
12469                 GL_DepthFunc(GL_LEQUAL);
12470                 GL_AlphaTest(false);
12471         }
12472 }
12473
12474 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12475 {
12476         int vi;
12477         int j;
12478         r_vertexgeneric_t *batchvertex;
12479         float c[4];
12480
12481         GL_AlphaTest(false);
12482         R_Mesh_ResetTextureState();
12483         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12484
12485         if(rsurface.texture && rsurface.texture->currentskinframe)
12486         {
12487                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12488                 c[3] *= rsurface.texture->currentalpha;
12489         }
12490         else
12491         {
12492                 c[0] = 1;
12493                 c[1] = 0;
12494                 c[2] = 1;
12495                 c[3] = 1;
12496         }
12497
12498         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12499         {
12500                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12501                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12502                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12503         }
12504
12505         // brighten it up (as texture value 127 means "unlit")
12506         c[0] *= 2 * r_refdef.view.colorscale;
12507         c[1] *= 2 * r_refdef.view.colorscale;
12508         c[2] *= 2 * r_refdef.view.colorscale;
12509
12510         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12511                 c[3] *= r_wateralpha.value;
12512
12513         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12514         {
12515                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12516                 GL_DepthMask(false);
12517         }
12518         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12519         {
12520                 GL_BlendFunc(GL_ONE, GL_ONE);
12521                 GL_DepthMask(false);
12522         }
12523         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12524         {
12525                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12526                 GL_DepthMask(false);
12527         }
12528         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12529         {
12530                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12531                 GL_DepthMask(false);
12532         }
12533         else
12534         {
12535                 GL_BlendFunc(GL_ONE, GL_ZERO);
12536                 GL_DepthMask(writedepth);
12537         }
12538
12539         if (r_showsurfaces.integer == 3)
12540         {
12541                 rsurface.passcolor4f = NULL;
12542
12543                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12544                 {
12545                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12546
12547                         rsurface.passcolor4f = NULL;
12548                         rsurface.passcolor4f_vertexbuffer = 0;
12549                         rsurface.passcolor4f_bufferoffset = 0;
12550                 }
12551                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12552                 {
12553                         qboolean applycolor = true;
12554                         float one = 1.0;
12555
12556                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12557
12558                         r_refdef.lightmapintensity = 1;
12559                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12560                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12561                 }
12562                 else
12563                 {
12564                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12565
12566                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12567                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12568                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12569                 }
12570
12571                 if(!rsurface.passcolor4f)
12572                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12573
12574                 RSurf_DrawBatch_GL11_ApplyAmbient();
12575                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12576                 if(r_refdef.fogenabled)
12577                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12578                 RSurf_DrawBatch_GL11_ClampColor();
12579
12580                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12581                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12582                 RSurf_DrawBatch();
12583         }
12584         else if (!r_refdef.view.showdebug)
12585         {
12586                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12587                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12588                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12589                 {
12590                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12591                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12592                 }
12593                 R_Mesh_PrepareVertices_Generic_Unlock();
12594                 RSurf_DrawBatch();
12595         }
12596         else if (r_showsurfaces.integer == 4)
12597         {
12598                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12599                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12600                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12601                 {
12602                         unsigned char c = vi << 3;
12603                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12604                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12605                 }
12606                 R_Mesh_PrepareVertices_Generic_Unlock();
12607                 RSurf_DrawBatch();
12608         }
12609         else if (r_showsurfaces.integer == 2)
12610         {
12611                 const int *e;
12612                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12613                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12614                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12615                 {
12616                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12617                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12618                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12619                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12620                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12621                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12622                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12623                 }
12624                 R_Mesh_PrepareVertices_Generic_Unlock();
12625                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12626         }
12627         else
12628         {
12629                 int texturesurfaceindex;
12630                 int k;
12631                 const msurface_t *surface;
12632                 unsigned char surfacecolor4ub[4];
12633                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12634                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12635                 vi = 0;
12636                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12637                 {
12638                         surface = texturesurfacelist[texturesurfaceindex];
12639                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12640                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12641                         for (j = 0;j < surface->num_vertices;j++)
12642                         {
12643                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12644                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12645                                 vi++;
12646                         }
12647                 }
12648                 R_Mesh_PrepareVertices_Generic_Unlock();
12649                 RSurf_DrawBatch();
12650         }
12651 }
12652
12653 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12654 {
12655         CHECKGLERROR
12656         RSurf_SetupDepthAndCulling();
12657         if (r_showsurfaces.integer)
12658         {
12659                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12660                 return;
12661         }
12662         switch (vid.renderpath)
12663         {
12664         case RENDERPATH_GL20:
12665         case RENDERPATH_CGGL:
12666         case RENDERPATH_D3D9:
12667         case RENDERPATH_D3D10:
12668         case RENDERPATH_D3D11:
12669                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12670                 break;
12671         case RENDERPATH_GL13:
12672                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12673                 break;
12674         case RENDERPATH_GL11:
12675                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12676                 break;
12677         }
12678         CHECKGLERROR
12679 }
12680
12681 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12682 {
12683         CHECKGLERROR
12684         RSurf_SetupDepthAndCulling();
12685         if (r_showsurfaces.integer)
12686         {
12687                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12688                 return;
12689         }
12690         switch (vid.renderpath)
12691         {
12692         case RENDERPATH_GL20:
12693         case RENDERPATH_CGGL:
12694         case RENDERPATH_D3D9:
12695         case RENDERPATH_D3D10:
12696         case RENDERPATH_D3D11:
12697                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12698                 break;
12699         case RENDERPATH_GL13:
12700                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12701                 break;
12702         case RENDERPATH_GL11:
12703                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12704                 break;
12705         }
12706         CHECKGLERROR
12707 }
12708
12709 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12710 {
12711         int i, j;
12712         int texturenumsurfaces, endsurface;
12713         texture_t *texture;
12714         const msurface_t *surface;
12715 #define MAXBATCH_TRANSPARENTSURFACES 256
12716         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12717
12718         // if the model is static it doesn't matter what value we give for
12719         // wantnormals and wanttangents, so this logic uses only rules applicable
12720         // to a model, knowing that they are meaningless otherwise
12721         if (ent == r_refdef.scene.worldentity)
12722                 RSurf_ActiveWorldEntity();
12723         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12724                 RSurf_ActiveModelEntity(ent, false, false, false);
12725         else
12726         {
12727                 switch (vid.renderpath)
12728                 {
12729                 case RENDERPATH_GL20:
12730                 case RENDERPATH_CGGL:
12731                 case RENDERPATH_D3D9:
12732                 case RENDERPATH_D3D10:
12733                 case RENDERPATH_D3D11:
12734                         RSurf_ActiveModelEntity(ent, true, true, false);
12735                         break;
12736                 case RENDERPATH_GL13:
12737                 case RENDERPATH_GL11:
12738                         RSurf_ActiveModelEntity(ent, true, false, false);
12739                         break;
12740                 }
12741         }
12742
12743         if (r_transparentdepthmasking.integer)
12744         {
12745                 qboolean setup = false;
12746                 for (i = 0;i < numsurfaces;i = j)
12747                 {
12748                         j = i + 1;
12749                         surface = rsurface.modelsurfaces + surfacelist[i];
12750                         texture = surface->texture;
12751                         rsurface.texture = R_GetCurrentTexture(texture);
12752                         rsurface.lightmaptexture = NULL;
12753                         rsurface.deluxemaptexture = NULL;
12754                         rsurface.uselightmaptexture = false;
12755                         // scan ahead until we find a different texture
12756                         endsurface = min(i + 1024, numsurfaces);
12757                         texturenumsurfaces = 0;
12758                         texturesurfacelist[texturenumsurfaces++] = surface;
12759                         for (;j < endsurface;j++)
12760                         {
12761                                 surface = rsurface.modelsurfaces + surfacelist[j];
12762                                 if (texture != surface->texture)
12763                                         break;
12764                                 texturesurfacelist[texturenumsurfaces++] = surface;
12765                         }
12766                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12767                                 continue;
12768                         // render the range of surfaces as depth
12769                         if (!setup)
12770                         {
12771                                 setup = true;
12772                                 GL_ColorMask(0,0,0,0);
12773                                 GL_Color(1,1,1,1);
12774                                 GL_DepthTest(true);
12775                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12776                                 GL_DepthMask(true);
12777                                 GL_AlphaTest(false);
12778                                 R_Mesh_ResetTextureState();
12779                                 R_SetupShader_DepthOrShadow();
12780                         }
12781                         RSurf_SetupDepthAndCulling();
12782                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12783                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12784                         RSurf_DrawBatch();
12785                 }
12786                 if (setup)
12787                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12788         }
12789
12790         for (i = 0;i < numsurfaces;i = j)
12791         {
12792                 j = i + 1;
12793                 surface = rsurface.modelsurfaces + surfacelist[i];
12794                 texture = surface->texture;
12795                 rsurface.texture = R_GetCurrentTexture(texture);
12796                 rsurface.lightmaptexture = surface->lightmaptexture;
12797                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12798                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12799                 // scan ahead until we find a different texture
12800                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12801                 texturenumsurfaces = 0;
12802                 texturesurfacelist[texturenumsurfaces++] = surface;
12803                 for (;j < endsurface;j++)
12804                 {
12805                         surface = rsurface.modelsurfaces + surfacelist[j];
12806                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12807                                 break;
12808                         texturesurfacelist[texturenumsurfaces++] = surface;
12809                 }
12810                 // render the range of surfaces
12811                 if (ent == r_refdef.scene.worldentity)
12812                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12813                 else
12814                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12815         }
12816         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12817         GL_AlphaTest(false);
12818 }
12819
12820 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12821 {
12822         // transparent surfaces get pushed off into the transparent queue
12823         int surfacelistindex;
12824         const msurface_t *surface;
12825         vec3_t tempcenter, center;
12826         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12827         {
12828                 surface = texturesurfacelist[surfacelistindex];
12829                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12830                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12831                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12832                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12833                 if (queueentity->transparent_offset) // transparent offset
12834                 {
12835                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12836                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12837                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12838                 }
12839                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12840         }
12841 }
12842
12843 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12844 {
12845         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12846                 return;
12847         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12848                 return;
12849         RSurf_SetupDepthAndCulling();
12850         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12851         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12852         RSurf_DrawBatch();
12853 }
12854
12855 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12856 {
12857         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12858         CHECKGLERROR
12859         if (depthonly)
12860                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12861         else if (prepass)
12862         {
12863                 if (!rsurface.texture->currentnumlayers)
12864                         return;
12865                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12866                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12867                 else
12868                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12869         }
12870         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12871                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12872         else if (!rsurface.texture->currentnumlayers)
12873                 return;
12874         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12875         {
12876                 // in the deferred case, transparent surfaces were queued during prepass
12877                 if (!r_shadow_usingdeferredprepass)
12878                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12879         }
12880         else
12881         {
12882                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12883                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12884         }
12885         CHECKGLERROR
12886 }
12887
12888 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12889 {
12890         int i, j;
12891         texture_t *texture;
12892         // break the surface list down into batches by texture and use of lightmapping
12893         for (i = 0;i < numsurfaces;i = j)
12894         {
12895                 j = i + 1;
12896                 // texture is the base texture pointer, rsurface.texture is the
12897                 // current frame/skin the texture is directing us to use (for example
12898                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12899                 // use skin 1 instead)
12900                 texture = surfacelist[i]->texture;
12901                 rsurface.texture = R_GetCurrentTexture(texture);
12902                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12903                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12904                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12905                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12906                 {
12907                         // if this texture is not the kind we want, skip ahead to the next one
12908                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12909                                 ;
12910                         continue;
12911                 }
12912                 // simply scan ahead until we find a different texture or lightmap state
12913                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12914                         ;
12915                 // render the range of surfaces
12916                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12917         }
12918 }
12919
12920 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12921 {
12922         CHECKGLERROR
12923         if (depthonly)
12924                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12925         else if (prepass)
12926         {
12927                 if (!rsurface.texture->currentnumlayers)
12928                         return;
12929                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12930                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12931                 else
12932                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12933         }
12934         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12935                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12936         else if (!rsurface.texture->currentnumlayers)
12937                 return;
12938         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12939         {
12940                 // in the deferred case, transparent surfaces were queued during prepass
12941                 if (!r_shadow_usingdeferredprepass)
12942                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12943         }
12944         else
12945         {
12946                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12947                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12948         }
12949         CHECKGLERROR
12950 }
12951
12952 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12953 {
12954         int i, j;
12955         texture_t *texture;
12956         // break the surface list down into batches by texture and use of lightmapping
12957         for (i = 0;i < numsurfaces;i = j)
12958         {
12959                 j = i + 1;
12960                 // texture is the base texture pointer, rsurface.texture is the
12961                 // current frame/skin the texture is directing us to use (for example
12962                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12963                 // use skin 1 instead)
12964                 texture = surfacelist[i]->texture;
12965                 rsurface.texture = R_GetCurrentTexture(texture);
12966                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12967                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12968                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12969                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12970                 {
12971                         // if this texture is not the kind we want, skip ahead to the next one
12972                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12973                                 ;
12974                         continue;
12975                 }
12976                 // simply scan ahead until we find a different texture or lightmap state
12977                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12978                         ;
12979                 // render the range of surfaces
12980                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12981         }
12982 }
12983
12984 float locboxvertex3f[6*4*3] =
12985 {
12986         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12987         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12988         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12989         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12990         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12991         1,0,0, 0,0,0, 0,1,0, 1,1,0
12992 };
12993
12994 unsigned short locboxelements[6*2*3] =
12995 {
12996          0, 1, 2, 0, 2, 3,
12997          4, 5, 6, 4, 6, 7,
12998          8, 9,10, 8,10,11,
12999         12,13,14, 12,14,15,
13000         16,17,18, 16,18,19,
13001         20,21,22, 20,22,23
13002 };
13003
13004 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13005 {
13006         int i, j;
13007         cl_locnode_t *loc = (cl_locnode_t *)ent;
13008         vec3_t mins, size;
13009         float vertex3f[6*4*3];
13010         CHECKGLERROR
13011         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13012         GL_DepthMask(false);
13013         GL_DepthRange(0, 1);
13014         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13015         GL_DepthTest(true);
13016         GL_CullFace(GL_NONE);
13017         R_EntityMatrix(&identitymatrix);
13018
13019         R_Mesh_ResetTextureState();
13020
13021         i = surfacelist[0];
13022         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13023                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13024                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13025                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13026
13027         if (VectorCompare(loc->mins, loc->maxs))
13028         {
13029                 VectorSet(size, 2, 2, 2);
13030                 VectorMA(loc->mins, -0.5f, size, mins);
13031         }
13032         else
13033         {
13034                 VectorCopy(loc->mins, mins);
13035                 VectorSubtract(loc->maxs, loc->mins, size);
13036         }
13037
13038         for (i = 0;i < 6*4*3;)
13039                 for (j = 0;j < 3;j++, i++)
13040                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13041
13042         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13043         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13044         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13045 }
13046
13047 void R_DrawLocs(void)
13048 {
13049         int index;
13050         cl_locnode_t *loc, *nearestloc;
13051         vec3_t center;
13052         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13053         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13054         {
13055                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13056                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13057         }
13058 }
13059
13060 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13061 {
13062         if (decalsystem->decals)
13063                 Mem_Free(decalsystem->decals);
13064         memset(decalsystem, 0, sizeof(*decalsystem));
13065 }
13066
13067 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)
13068 {
13069         tridecal_t *decal;
13070         tridecal_t *decals;
13071         int i;
13072
13073         // expand or initialize the system
13074         if (decalsystem->maxdecals <= decalsystem->numdecals)
13075         {
13076                 decalsystem_t old = *decalsystem;
13077                 qboolean useshortelements;
13078                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13079                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13080                 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)));
13081                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13082                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13083                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13084                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13085                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13086                 if (decalsystem->numdecals)
13087                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13088                 if (old.decals)
13089                         Mem_Free(old.decals);
13090                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13091                         decalsystem->element3i[i] = i;
13092                 if (useshortelements)
13093                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13094                                 decalsystem->element3s[i] = i;
13095         }
13096
13097         // grab a decal and search for another free slot for the next one
13098         decals = decalsystem->decals;
13099         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13100         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13101                 ;
13102         decalsystem->freedecal = i;
13103         if (decalsystem->numdecals <= i)
13104                 decalsystem->numdecals = i + 1;
13105
13106         // initialize the decal
13107         decal->lived = 0;
13108         decal->triangleindex = triangleindex;
13109         decal->surfaceindex = surfaceindex;
13110         decal->decalsequence = decalsequence;
13111         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13112         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13113         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13114         decal->color4ub[0][3] = 255;
13115         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13116         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13117         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13118         decal->color4ub[1][3] = 255;
13119         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13120         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13121         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13122         decal->color4ub[2][3] = 255;
13123         decal->vertex3f[0][0] = v0[0];
13124         decal->vertex3f[0][1] = v0[1];
13125         decal->vertex3f[0][2] = v0[2];
13126         decal->vertex3f[1][0] = v1[0];
13127         decal->vertex3f[1][1] = v1[1];
13128         decal->vertex3f[1][2] = v1[2];
13129         decal->vertex3f[2][0] = v2[0];
13130         decal->vertex3f[2][1] = v2[1];
13131         decal->vertex3f[2][2] = v2[2];
13132         decal->texcoord2f[0][0] = t0[0];
13133         decal->texcoord2f[0][1] = t0[1];
13134         decal->texcoord2f[1][0] = t1[0];
13135         decal->texcoord2f[1][1] = t1[1];
13136         decal->texcoord2f[2][0] = t2[0];
13137         decal->texcoord2f[2][1] = t2[1];
13138 }
13139
13140 extern cvar_t cl_decals_bias;
13141 extern cvar_t cl_decals_models;
13142 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13143 // baseparms, parms, temps
13144 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)
13145 {
13146         int cornerindex;
13147         int index;
13148         float v[9][3];
13149         const float *vertex3f;
13150         int numpoints;
13151         float points[2][9][3];
13152         float temp[3];
13153         float tc[9][2];
13154         float f;
13155         float c[9][4];
13156         const int *e;
13157
13158         e = rsurface.modelelement3i + 3*triangleindex;
13159
13160         vertex3f = rsurface.modelvertex3f;
13161
13162         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13163         {
13164                 index = 3*e[cornerindex];
13165                 VectorCopy(vertex3f + index, v[cornerindex]);
13166         }
13167         // cull backfaces
13168         //TriangleNormal(v[0], v[1], v[2], normal);
13169         //if (DotProduct(normal, localnormal) < 0.0f)
13170         //      continue;
13171         // clip by each of the box planes formed from the projection matrix
13172         // if anything survives, we emit the decal
13173         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]);
13174         if (numpoints < 3)
13175                 return;
13176         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]);
13177         if (numpoints < 3)
13178                 return;
13179         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]);
13180         if (numpoints < 3)
13181                 return;
13182         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]);
13183         if (numpoints < 3)
13184                 return;
13185         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]);
13186         if (numpoints < 3)
13187                 return;
13188         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]);
13189         if (numpoints < 3)
13190                 return;
13191         // some part of the triangle survived, so we have to accept it...
13192         if (dynamic)
13193         {
13194                 // dynamic always uses the original triangle
13195                 numpoints = 3;
13196                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13197                 {
13198                         index = 3*e[cornerindex];
13199                         VectorCopy(vertex3f + index, v[cornerindex]);
13200                 }
13201         }
13202         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13203         {
13204                 // convert vertex positions to texcoords
13205                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13206                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13207                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13208                 // calculate distance fade from the projection origin
13209                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13210                 f = bound(0.0f, f, 1.0f);
13211                 c[cornerindex][0] = r * f;
13212                 c[cornerindex][1] = g * f;
13213                 c[cornerindex][2] = b * f;
13214                 c[cornerindex][3] = 1.0f;
13215                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13216         }
13217         if (dynamic)
13218                 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);
13219         else
13220                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13221                         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);
13222 }
13223 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)
13224 {
13225         matrix4x4_t projection;
13226         decalsystem_t *decalsystem;
13227         qboolean dynamic;
13228         dp_model_t *model;
13229         const msurface_t *surface;
13230         const msurface_t *surfaces;
13231         const int *surfacelist;
13232         const texture_t *texture;
13233         int numtriangles;
13234         int numsurfacelist;
13235         int surfacelistindex;
13236         int surfaceindex;
13237         int triangleindex;
13238         float localorigin[3];
13239         float localnormal[3];
13240         float localmins[3];
13241         float localmaxs[3];
13242         float localsize;
13243         //float normal[3];
13244         float planes[6][4];
13245         float angles[3];
13246         bih_t *bih;
13247         int bih_triangles_count;
13248         int bih_triangles[256];
13249         int bih_surfaces[256];
13250
13251         decalsystem = &ent->decalsystem;
13252         model = ent->model;
13253         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13254         {
13255                 R_DecalSystem_Reset(&ent->decalsystem);
13256                 return;
13257         }
13258
13259         if (!model->brush.data_leafs && !cl_decals_models.integer)
13260         {
13261                 if (decalsystem->model)
13262                         R_DecalSystem_Reset(decalsystem);
13263                 return;
13264         }
13265
13266         if (decalsystem->model != model)
13267                 R_DecalSystem_Reset(decalsystem);
13268         decalsystem->model = model;
13269
13270         RSurf_ActiveModelEntity(ent, false, false, false);
13271
13272         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13273         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13274         VectorNormalize(localnormal);
13275         localsize = worldsize*rsurface.inversematrixscale;
13276         localmins[0] = localorigin[0] - localsize;
13277         localmins[1] = localorigin[1] - localsize;
13278         localmins[2] = localorigin[2] - localsize;
13279         localmaxs[0] = localorigin[0] + localsize;
13280         localmaxs[1] = localorigin[1] + localsize;
13281         localmaxs[2] = localorigin[2] + localsize;
13282
13283         //VectorCopy(localnormal, planes[4]);
13284         //VectorVectors(planes[4], planes[2], planes[0]);
13285         AnglesFromVectors(angles, localnormal, NULL, false);
13286         AngleVectors(angles, planes[0], planes[2], planes[4]);
13287         VectorNegate(planes[0], planes[1]);
13288         VectorNegate(planes[2], planes[3]);
13289         VectorNegate(planes[4], planes[5]);
13290         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13291         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13292         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13293         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13294         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13295         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13296
13297 #if 1
13298 // works
13299 {
13300         matrix4x4_t forwardprojection;
13301         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13302         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13303 }
13304 #else
13305 // broken
13306 {
13307         float projectionvector[4][3];
13308         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13309         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13310         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13311         projectionvector[0][0] = planes[0][0] * ilocalsize;
13312         projectionvector[0][1] = planes[1][0] * ilocalsize;
13313         projectionvector[0][2] = planes[2][0] * ilocalsize;
13314         projectionvector[1][0] = planes[0][1] * ilocalsize;
13315         projectionvector[1][1] = planes[1][1] * ilocalsize;
13316         projectionvector[1][2] = planes[2][1] * ilocalsize;
13317         projectionvector[2][0] = planes[0][2] * ilocalsize;
13318         projectionvector[2][1] = planes[1][2] * ilocalsize;
13319         projectionvector[2][2] = planes[2][2] * ilocalsize;
13320         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13321         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13322         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13323         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13324 }
13325 #endif
13326
13327         dynamic = model->surfmesh.isanimated;
13328         numsurfacelist = model->nummodelsurfaces;
13329         surfacelist = model->sortedmodelsurfaces;
13330         surfaces = model->data_surfaces;
13331
13332         bih = NULL;
13333         bih_triangles_count = -1;
13334         if(!dynamic)
13335         {
13336                 if(model->render_bih.numleafs)
13337                         bih = &model->render_bih;
13338                 else if(model->collision_bih.numleafs)
13339                         bih = &model->collision_bih;
13340         }
13341         if(bih)
13342                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13343         if(bih_triangles_count == 0)
13344                 return;
13345         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13346                 return;
13347         if(bih_triangles_count > 0)
13348         {
13349                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13350                 {
13351                         surfaceindex = bih_surfaces[triangleindex];
13352                         surface = surfaces + surfaceindex;
13353                         texture = surface->texture;
13354                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13355                                 continue;
13356                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13357                                 continue;
13358                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13359                 }
13360         }
13361         else
13362         {
13363                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13364                 {
13365                         surfaceindex = surfacelist[surfacelistindex];
13366                         surface = surfaces + surfaceindex;
13367                         // check cull box first because it rejects more than any other check
13368                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13369                                 continue;
13370                         // skip transparent surfaces
13371                         texture = surface->texture;
13372                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13373                                 continue;
13374                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13375                                 continue;
13376                         numtriangles = surface->num_triangles;
13377                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13378                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13379                 }
13380         }
13381 }
13382
13383 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13384 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)
13385 {
13386         int renderentityindex;
13387         float worldmins[3];
13388         float worldmaxs[3];
13389         entity_render_t *ent;
13390
13391         if (!cl_decals_newsystem.integer)
13392                 return;
13393
13394         worldmins[0] = worldorigin[0] - worldsize;
13395         worldmins[1] = worldorigin[1] - worldsize;
13396         worldmins[2] = worldorigin[2] - worldsize;
13397         worldmaxs[0] = worldorigin[0] + worldsize;
13398         worldmaxs[1] = worldorigin[1] + worldsize;
13399         worldmaxs[2] = worldorigin[2] + worldsize;
13400
13401         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13402
13403         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13404         {
13405                 ent = r_refdef.scene.entities[renderentityindex];
13406                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13407                         continue;
13408
13409                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13410         }
13411 }
13412
13413 typedef struct r_decalsystem_splatqueue_s
13414 {
13415         vec3_t worldorigin;
13416         vec3_t worldnormal;
13417         float color[4];
13418         float tcrange[4];
13419         float worldsize;
13420         int decalsequence;
13421 }
13422 r_decalsystem_splatqueue_t;
13423
13424 int r_decalsystem_numqueued = 0;
13425 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13426
13427 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)
13428 {
13429         r_decalsystem_splatqueue_t *queue;
13430
13431         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13432                 return;
13433
13434         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13435         VectorCopy(worldorigin, queue->worldorigin);
13436         VectorCopy(worldnormal, queue->worldnormal);
13437         Vector4Set(queue->color, r, g, b, a);
13438         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13439         queue->worldsize = worldsize;
13440         queue->decalsequence = cl.decalsequence++;
13441 }
13442
13443 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13444 {
13445         int i;
13446         r_decalsystem_splatqueue_t *queue;
13447
13448         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13449                 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);
13450         r_decalsystem_numqueued = 0;
13451 }
13452
13453 extern cvar_t cl_decals_max;
13454 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13455 {
13456         int i;
13457         decalsystem_t *decalsystem = &ent->decalsystem;
13458         int numdecals;
13459         int killsequence;
13460         tridecal_t *decal;
13461         float frametime;
13462         float lifetime;
13463
13464         if (!decalsystem->numdecals)
13465                 return;
13466
13467         if (r_showsurfaces.integer)
13468                 return;
13469
13470         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13471         {
13472                 R_DecalSystem_Reset(decalsystem);
13473                 return;
13474         }
13475
13476         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13477         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13478
13479         if (decalsystem->lastupdatetime)
13480                 frametime = (cl.time - decalsystem->lastupdatetime);
13481         else
13482                 frametime = 0;
13483         decalsystem->lastupdatetime = cl.time;
13484         decal = decalsystem->decals;
13485         numdecals = decalsystem->numdecals;
13486
13487         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13488         {
13489                 if (decal->color4ub[0][3])
13490                 {
13491                         decal->lived += frametime;
13492                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13493                         {
13494                                 memset(decal, 0, sizeof(*decal));
13495                                 if (decalsystem->freedecal > i)
13496                                         decalsystem->freedecal = i;
13497                         }
13498                 }
13499         }
13500         decal = decalsystem->decals;
13501         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13502                 numdecals--;
13503
13504         // collapse the array by shuffling the tail decals into the gaps
13505         for (;;)
13506         {
13507                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13508                         decalsystem->freedecal++;
13509                 if (decalsystem->freedecal == numdecals)
13510                         break;
13511                 decal[decalsystem->freedecal] = decal[--numdecals];
13512         }
13513
13514         decalsystem->numdecals = numdecals;
13515
13516         if (numdecals <= 0)
13517         {
13518                 // if there are no decals left, reset decalsystem
13519                 R_DecalSystem_Reset(decalsystem);
13520         }
13521 }
13522
13523 extern skinframe_t *decalskinframe;
13524 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13525 {
13526         int i;
13527         decalsystem_t *decalsystem = &ent->decalsystem;
13528         int numdecals;
13529         tridecal_t *decal;
13530         float faderate;
13531         float alpha;
13532         float *v3f;
13533         float *c4f;
13534         float *t2f;
13535         const int *e;
13536         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13537         int numtris = 0;
13538
13539         numdecals = decalsystem->numdecals;
13540         if (!numdecals)
13541                 return;
13542
13543         if (r_showsurfaces.integer)
13544                 return;
13545
13546         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13547         {
13548                 R_DecalSystem_Reset(decalsystem);
13549                 return;
13550         }
13551
13552         // if the model is static it doesn't matter what value we give for
13553         // wantnormals and wanttangents, so this logic uses only rules applicable
13554         // to a model, knowing that they are meaningless otherwise
13555         if (ent == r_refdef.scene.worldentity)
13556                 RSurf_ActiveWorldEntity();
13557         else
13558                 RSurf_ActiveModelEntity(ent, false, false, false);
13559
13560         decalsystem->lastupdatetime = cl.time;
13561         decal = decalsystem->decals;
13562
13563         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13564
13565         // update vertex positions for animated models
13566         v3f = decalsystem->vertex3f;
13567         c4f = decalsystem->color4f;
13568         t2f = decalsystem->texcoord2f;
13569         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13570         {
13571                 if (!decal->color4ub[0][3])
13572                         continue;
13573
13574                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13575                         continue;
13576
13577                 // update color values for fading decals
13578                 if (decal->lived >= cl_decals_time.value)
13579                 {
13580                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13581                         alpha *= (1.0f/255.0f);
13582                 }
13583                 else
13584                         alpha = 1.0f/255.0f;
13585
13586                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13587                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13588                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13589                 c4f[ 3] = 1;
13590                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13591                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13592                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13593                 c4f[ 7] = 1;
13594                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13595                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13596                 c4f[10] = decal->color4ub[2][2] * alpha;
13597                 c4f[11] = 1;
13598
13599                 t2f[0] = decal->texcoord2f[0][0];
13600                 t2f[1] = decal->texcoord2f[0][1];
13601                 t2f[2] = decal->texcoord2f[1][0];
13602                 t2f[3] = decal->texcoord2f[1][1];
13603                 t2f[4] = decal->texcoord2f[2][0];
13604                 t2f[5] = decal->texcoord2f[2][1];
13605
13606                 // update vertex positions for animated models
13607                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13608                 {
13609                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13610                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13611                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13612                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13613                 }
13614                 else
13615                 {
13616                         VectorCopy(decal->vertex3f[0], v3f);
13617                         VectorCopy(decal->vertex3f[1], v3f + 3);
13618                         VectorCopy(decal->vertex3f[2], v3f + 6);
13619                 }
13620
13621                 if (r_refdef.fogenabled)
13622                 {
13623                         alpha = RSurf_FogVertex(v3f);
13624                         VectorScale(c4f, alpha, c4f);
13625                         alpha = RSurf_FogVertex(v3f + 3);
13626                         VectorScale(c4f + 4, alpha, c4f + 4);
13627                         alpha = RSurf_FogVertex(v3f + 6);
13628                         VectorScale(c4f + 8, alpha, c4f + 8);
13629                 }
13630
13631                 v3f += 9;
13632                 c4f += 12;
13633                 t2f += 6;
13634                 numtris++;
13635         }
13636
13637         if (numtris > 0)
13638         {
13639                 r_refdef.stats.drawndecals += numtris;
13640
13641                 // now render the decals all at once
13642                 // (this assumes they all use one particle font texture!)
13643                 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);
13644                 R_Mesh_ResetTextureState();
13645                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13646                 GL_DepthMask(false);
13647                 GL_DepthRange(0, 1);
13648                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13649                 GL_DepthTest(true);
13650                 GL_CullFace(GL_NONE);
13651                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13652                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13653                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13654         }
13655 }
13656
13657 static void R_DrawModelDecals(void)
13658 {
13659         int i, numdecals;
13660
13661         // fade faster when there are too many decals
13662         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13663         for (i = 0;i < r_refdef.scene.numentities;i++)
13664                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13665
13666         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13667         for (i = 0;i < r_refdef.scene.numentities;i++)
13668                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13669                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13670
13671         R_DecalSystem_ApplySplatEntitiesQueue();
13672
13673         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13674         for (i = 0;i < r_refdef.scene.numentities;i++)
13675                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13676
13677         r_refdef.stats.totaldecals += numdecals;
13678
13679         if (r_showsurfaces.integer)
13680                 return;
13681
13682         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13683
13684         for (i = 0;i < r_refdef.scene.numentities;i++)
13685         {
13686                 if (!r_refdef.viewcache.entityvisible[i])
13687                         continue;
13688                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13689                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13690         }
13691 }
13692
13693 extern cvar_t mod_collision_bih;
13694 void R_DrawDebugModel(void)
13695 {
13696         entity_render_t *ent = rsurface.entity;
13697         int i, j, k, l, flagsmask;
13698         const msurface_t *surface;
13699         dp_model_t *model = ent->model;
13700         vec3_t v;
13701
13702         switch(vid.renderpath)
13703         {
13704         case RENDERPATH_GL11:
13705         case RENDERPATH_GL13:
13706         case RENDERPATH_GL20:
13707         case RENDERPATH_CGGL:
13708                 break;
13709         case RENDERPATH_D3D9:
13710                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13711                 return;
13712         case RENDERPATH_D3D10:
13713                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13714                 return;
13715         case RENDERPATH_D3D11:
13716                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13717                 return;
13718         }
13719
13720         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13721
13722         R_Mesh_ResetTextureState();
13723         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13724         GL_DepthRange(0, 1);
13725         GL_DepthTest(!r_showdisabledepthtest.integer);
13726         GL_DepthMask(false);
13727         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13728
13729         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13730         {
13731                 int triangleindex;
13732                 int bihleafindex;
13733                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13734                 const q3mbrush_t *brush;
13735                 const bih_t *bih = &model->collision_bih;
13736                 const bih_leaf_t *bihleaf;
13737                 float vertex3f[3][3];
13738                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13739                 cullbox = false;
13740                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13741                 {
13742                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13743                                 continue;
13744                         switch (bihleaf->type)
13745                         {
13746                         case BIH_BRUSH:
13747                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13748                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13749                                 {
13750                                         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);
13751                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13752                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13753                                 }
13754                                 break;
13755                         case BIH_COLLISIONTRIANGLE:
13756                                 triangleindex = bihleaf->itemindex;
13757                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13758                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13759                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13760                                 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);
13761                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13762                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13763                                 break;
13764                         case BIH_RENDERTRIANGLE:
13765                                 triangleindex = bihleaf->itemindex;
13766                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13767                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13768                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13769                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
13770                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13771                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13772                                 break;
13773                         }
13774                 }
13775         }
13776
13777         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13778
13779         if (r_showtris.integer || r_shownormals.integer)
13780         {
13781                 if (r_showdisabledepthtest.integer)
13782                 {
13783                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13784                         GL_DepthMask(false);
13785                 }
13786                 else
13787                 {
13788                         GL_BlendFunc(GL_ONE, GL_ZERO);
13789                         GL_DepthMask(true);
13790                 }
13791                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13792                 {
13793                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13794                                 continue;
13795                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13796                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13797                         {
13798                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13799                                 if (r_showtris.value > 0)
13800                                 {
13801                                         if (!rsurface.texture->currentlayers->depthmask)
13802                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13803                                         else if (ent == r_refdef.scene.worldentity)
13804                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13805                                         else
13806                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13807                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13808                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13809                                         RSurf_DrawBatch();
13810                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13811                                         CHECKGLERROR
13812                                 }
13813                                 if (r_shownormals.value < 0)
13814                                 {
13815                                         qglBegin(GL_LINES);
13816                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13817                                         {
13818                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13819                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13820                                                 qglVertex3f(v[0], v[1], v[2]);
13821                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13822                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13823                                                 qglVertex3f(v[0], v[1], v[2]);
13824                                         }
13825                                         qglEnd();
13826                                         CHECKGLERROR
13827                                 }
13828                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13829                                 {
13830                                         qglBegin(GL_LINES);
13831                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13832                                         {
13833                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13834                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13835                                                 qglVertex3f(v[0], v[1], v[2]);
13836                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13837                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13838                                                 qglVertex3f(v[0], v[1], v[2]);
13839                                         }
13840                                         qglEnd();
13841                                         CHECKGLERROR
13842                                         qglBegin(GL_LINES);
13843                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13844                                         {
13845                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13846                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13847                                                 qglVertex3f(v[0], v[1], v[2]);
13848                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13849                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13850                                                 qglVertex3f(v[0], v[1], v[2]);
13851                                         }
13852                                         qglEnd();
13853                                         CHECKGLERROR
13854                                         qglBegin(GL_LINES);
13855                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13856                                         {
13857                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13858                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13859                                                 qglVertex3f(v[0], v[1], v[2]);
13860                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13861                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13862                                                 qglVertex3f(v[0], v[1], v[2]);
13863                                         }
13864                                         qglEnd();
13865                                         CHECKGLERROR
13866                                 }
13867                         }
13868                 }
13869                 rsurface.texture = NULL;
13870         }
13871 }
13872
13873 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13874 int r_maxsurfacelist = 0;
13875 const msurface_t **r_surfacelist = NULL;
13876 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13877 {
13878         int i, j, endj, flagsmask;
13879         dp_model_t *model = r_refdef.scene.worldmodel;
13880         msurface_t *surfaces;
13881         unsigned char *update;
13882         int numsurfacelist = 0;
13883         if (model == NULL)
13884                 return;
13885
13886         if (r_maxsurfacelist < model->num_surfaces)
13887         {
13888                 r_maxsurfacelist = model->num_surfaces;
13889                 if (r_surfacelist)
13890                         Mem_Free((msurface_t**)r_surfacelist);
13891                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13892         }
13893
13894         RSurf_ActiveWorldEntity();
13895
13896         surfaces = model->data_surfaces;
13897         update = model->brushq1.lightmapupdateflags;
13898
13899         // update light styles on this submodel
13900         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13901         {
13902                 model_brush_lightstyleinfo_t *style;
13903                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13904                 {
13905                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13906                         {
13907                                 int *list = style->surfacelist;
13908                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13909                                 for (j = 0;j < style->numsurfaces;j++)
13910                                         update[list[j]] = true;
13911                         }
13912                 }
13913         }
13914
13915         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13916
13917         if (debug)
13918         {
13919                 R_DrawDebugModel();
13920                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13921                 return;
13922         }
13923
13924         rsurface.lightmaptexture = NULL;
13925         rsurface.deluxemaptexture = NULL;
13926         rsurface.uselightmaptexture = false;
13927         rsurface.texture = NULL;
13928         rsurface.rtlight = NULL;
13929         numsurfacelist = 0;
13930         // add visible surfaces to draw list
13931         for (i = 0;i < model->nummodelsurfaces;i++)
13932         {
13933                 j = model->sortedmodelsurfaces[i];
13934                 if (r_refdef.viewcache.world_surfacevisible[j])
13935                         r_surfacelist[numsurfacelist++] = surfaces + j;
13936         }
13937         // update lightmaps if needed
13938         if (model->brushq1.firstrender)
13939         {
13940                 model->brushq1.firstrender = false;
13941                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13942                         if (update[j])
13943                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13944         }
13945         else if (update)
13946         {
13947                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13948                         if (r_refdef.viewcache.world_surfacevisible[j])
13949                                 if (update[j])
13950                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13951         }
13952         // don't do anything if there were no surfaces
13953         if (!numsurfacelist)
13954         {
13955                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13956                 return;
13957         }
13958         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13959         GL_AlphaTest(false);
13960
13961         // add to stats if desired
13962         if (r_speeds.integer && !skysurfaces && !depthonly)
13963         {
13964                 r_refdef.stats.world_surfaces += numsurfacelist;
13965                 for (j = 0;j < numsurfacelist;j++)
13966                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13967         }
13968
13969         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13970 }
13971
13972 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13973 {
13974         int i, j, endj, flagsmask;
13975         dp_model_t *model = ent->model;
13976         msurface_t *surfaces;
13977         unsigned char *update;
13978         int numsurfacelist = 0;
13979         if (model == NULL)
13980                 return;
13981
13982         if (r_maxsurfacelist < model->num_surfaces)
13983         {
13984                 r_maxsurfacelist = model->num_surfaces;
13985                 if (r_surfacelist)
13986                         Mem_Free((msurface_t **)r_surfacelist);
13987                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13988         }
13989
13990         // if the model is static it doesn't matter what value we give for
13991         // wantnormals and wanttangents, so this logic uses only rules applicable
13992         // to a model, knowing that they are meaningless otherwise
13993         if (ent == r_refdef.scene.worldentity)
13994                 RSurf_ActiveWorldEntity();
13995         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13996                 RSurf_ActiveModelEntity(ent, false, false, false);
13997         else if (prepass)
13998                 RSurf_ActiveModelEntity(ent, true, true, true);
13999         else if (depthonly)
14000         {
14001                 switch (vid.renderpath)
14002                 {
14003                 case RENDERPATH_GL20:
14004                 case RENDERPATH_CGGL:
14005                 case RENDERPATH_D3D9:
14006                 case RENDERPATH_D3D10:
14007                 case RENDERPATH_D3D11:
14008                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14009                         break;
14010                 case RENDERPATH_GL13:
14011                 case RENDERPATH_GL11:
14012                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14013                         break;
14014                 }
14015         }
14016         else
14017         {
14018                 switch (vid.renderpath)
14019                 {
14020                 case RENDERPATH_GL20:
14021                 case RENDERPATH_CGGL:
14022                 case RENDERPATH_D3D9:
14023                 case RENDERPATH_D3D10:
14024                 case RENDERPATH_D3D11:
14025                         RSurf_ActiveModelEntity(ent, true, true, false);
14026                         break;
14027                 case RENDERPATH_GL13:
14028                 case RENDERPATH_GL11:
14029                         RSurf_ActiveModelEntity(ent, true, false, false);
14030                         break;
14031                 }
14032         }
14033
14034         surfaces = model->data_surfaces;
14035         update = model->brushq1.lightmapupdateflags;
14036
14037         // update light styles
14038         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14039         {
14040                 model_brush_lightstyleinfo_t *style;
14041                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14042                 {
14043                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14044                         {
14045                                 int *list = style->surfacelist;
14046                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14047                                 for (j = 0;j < style->numsurfaces;j++)
14048                                         update[list[j]] = true;
14049                         }
14050                 }
14051         }
14052
14053         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14054
14055         if (debug)
14056         {
14057                 R_DrawDebugModel();
14058                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14059                 return;
14060         }
14061
14062         rsurface.lightmaptexture = NULL;
14063         rsurface.deluxemaptexture = NULL;
14064         rsurface.uselightmaptexture = false;
14065         rsurface.texture = NULL;
14066         rsurface.rtlight = NULL;
14067         numsurfacelist = 0;
14068         // add visible surfaces to draw list
14069         for (i = 0;i < model->nummodelsurfaces;i++)
14070                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14071         // don't do anything if there were no surfaces
14072         if (!numsurfacelist)
14073         {
14074                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14075                 return;
14076         }
14077         // update lightmaps if needed
14078         if (update)
14079         {
14080                 int updated = 0;
14081                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14082                 {
14083                         if (update[j])
14084                         {
14085                                 updated++;
14086                                 R_BuildLightMap(ent, surfaces + j);
14087                         }
14088                 }
14089         }
14090         if (update)
14091                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14092                         if (update[j])
14093                                 R_BuildLightMap(ent, surfaces + j);
14094         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14095         GL_AlphaTest(false);
14096
14097         // add to stats if desired
14098         if (r_speeds.integer && !skysurfaces && !depthonly)
14099         {
14100                 r_refdef.stats.entities_surfaces += numsurfacelist;
14101                 for (j = 0;j < numsurfacelist;j++)
14102                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14103         }
14104
14105         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14106 }
14107
14108 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14109 {
14110         static texture_t texture;
14111         static msurface_t surface;
14112         const msurface_t *surfacelist = &surface;
14113
14114         // fake enough texture and surface state to render this geometry
14115
14116         texture.update_lastrenderframe = -1; // regenerate this texture
14117         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14118         texture.currentskinframe = skinframe;
14119         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14120         texture.offsetmapping = OFFSETMAPPING_OFF;
14121         texture.offsetscale = 1;
14122         texture.specularscalemod = 1;
14123         texture.specularpowermod = 1;
14124
14125         surface.texture = &texture;
14126         surface.num_triangles = numtriangles;
14127         surface.num_firsttriangle = firsttriangle;
14128         surface.num_vertices = numvertices;
14129         surface.num_firstvertex = firstvertex;
14130
14131         // now render it
14132         rsurface.texture = R_GetCurrentTexture(surface.texture);
14133         rsurface.lightmaptexture = NULL;
14134         rsurface.deluxemaptexture = NULL;
14135         rsurface.uselightmaptexture = false;
14136         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14137 }
14138
14139 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)
14140 {
14141         static msurface_t surface;
14142         const msurface_t *surfacelist = &surface;
14143
14144         // fake enough texture and surface state to render this geometry
14145
14146         surface.texture = texture;
14147         surface.num_triangles = numtriangles;
14148         surface.num_firsttriangle = firsttriangle;
14149         surface.num_vertices = numvertices;
14150         surface.num_firstvertex = firstvertex;
14151
14152         // now render it
14153         rsurface.texture = R_GetCurrentTexture(surface.texture);
14154         rsurface.lightmaptexture = NULL;
14155         rsurface.deluxemaptexture = NULL;
14156         rsurface.uselightmaptexture = false;
14157         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14158 }