]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
change clamping logic
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
146
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
170
171 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
172
173 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
502         }
503 }
504
505 static void R_BuildFogHeightTexture(void)
506 {
507         unsigned char *inpixels;
508         int size;
509         int x;
510         int y;
511         int j;
512         float c[4];
513         float f;
514         inpixels = NULL;
515         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516         if (r_refdef.fogheighttexturename[0])
517                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
518         if (!inpixels)
519         {
520                 r_refdef.fog_height_tablesize = 0;
521                 if (r_texture_fogheighttexture)
522                         R_FreeTexture(r_texture_fogheighttexture);
523                 r_texture_fogheighttexture = NULL;
524                 if (r_refdef.fog_height_table2d)
525                         Mem_Free(r_refdef.fog_height_table2d);
526                 r_refdef.fog_height_table2d = NULL;
527                 if (r_refdef.fog_height_table1d)
528                         Mem_Free(r_refdef.fog_height_table1d);
529                 r_refdef.fog_height_table1d = NULL;
530                 return;
531         }
532         size = image_width;
533         r_refdef.fog_height_tablesize = size;
534         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
537         Mem_Free(inpixels);
538         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
539         // average fog color table accounting for every fog layer between a point
540         // and the camera.  (Note: attenuation is handled separately!)
541         for (y = 0;y < size;y++)
542         {
543                 for (x = 0;x < size;x++)
544                 {
545                         Vector4Clear(c);
546                         f = 0;
547                         if (x < y)
548                         {
549                                 for (j = x;j <= y;j++)
550                                 {
551                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
552                                         f++;
553                                 }
554                         }
555                         else
556                         {
557                                 for (j = x;j >= y;j--)
558                                 {
559                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
560                                         f++;
561                                 }
562                         }
563                         f = 1.0f / f;
564                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
568                 }
569         }
570         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
571 }
572
573 //=======================================================================================================================================================
574
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "#   extension GL_EXT_gpu_shader4 : enable\n"
593 "# endif\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "#   extension GL_ARB_texture_gather : enable\n"
596 "# else\n"
597 "#   ifdef GL_AMD_texture_texture4\n"
598 "#     extension GL_AMD_texture_texture4 : enable\n"
599 "#   endif\n"
600 "# endif\n"
601 "#endif\n"
602 "\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
605 "//#endif\n"
606 "\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
612 "//#else\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
617 "//#endif\n"
618 "\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
621 "#endif\n"
622 "\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
625 "void main(void)\n"
626 "{\n"
627 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
628 "}\n"
629 "#endif\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
631 "\n"
632 "\n"
633 "\n"
634 "\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
641 "}\n"
642 "#endif\n"
643 "\n"
644 "#ifdef FRAGMENT_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_FragColor = gl_Color;\n"
648 "}\n"
649 "#endif\n"
650 "#else // !MODE_SHOWDEPTH\n"
651 "\n"
652 "\n"
653 "\n"
654 "\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
658 "\n"
659 "#ifdef VERTEX_SHADER\n"
660 "void main(void)\n"
661 "{\n"
662 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USEBLOOM\n"
665 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
666 "#endif\n"
667 "}\n"
668 "#endif\n"
669 "\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
672 "#ifdef USEBLOOM\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
675 "#endif\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
678 "#endif\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
681 "#endif\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
684 "#endif\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
695 "#ifdef USEBLOOM\n"
696 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
697 "#endif\n"
698 "#ifdef USEVIEWTINT\n"
699 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
700 "#endif\n"
701 "\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
705 "       float sobel = 1.0;\n"
706 "       // vec2 ts = textureSize(Texture_First, 0);\n"
707 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 "       vec2 px = PixelSize;\n"
709 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
711 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
714 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
717 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
720 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
738 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
739 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USESATURATION\n"
744 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USEGAMMARAMPS\n"
751 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
754 "#endif\n"
755 "}\n"
756 "#endif\n"
757 "#else // !MODE_POSTPROCESS\n"
758 "\n"
759 "\n"
760 "\n"
761 "\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
765 "#endif\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
768 "#endif\n"
769 "#ifdef VERTEX_SHADER\n"
770 "void main(void)\n"
771 "{\n"
772 "       gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
775 "#endif\n"
776 "#ifdef USESPECULAR\n"
777 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
778 "#endif\n"
779 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
780 "}\n"
781 "#endif\n"
782 "\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
789 "#endif\n"
790 "\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
796 "#endif\n"
797 "\n"
798 "#ifdef USESPECULAR\n"
799 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 "       gl_FragColor *= tex2;\n"
802 "# endif\n"
803 "# ifdef USEGLOW\n"
804 "       gl_FragColor += tex2;\n"
805 "# endif\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
808 "# endif\n"
809 "#endif\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_GENERIC\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
820 "void main(void)\n"
821 "{\n"
822 "       gl_FrontColor = gl_Color;\n"
823 "       TexCoord = gl_MultiTexCoord0.xy;\n"
824 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
825 "}\n"
826 "#endif\n"
827 "\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
831 "\n"
832 "void main(void)\n"
833 "{\n"
834 "       int i;\n"
835 "       vec2 tc = TexCoord;\n"
836 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 "       tc += BloomBlur_Parameters.xy;\n"
838 "       for (i = 1;i < SAMPLES;i++)\n"
839 "       {\n"
840 "               color += texture2D(Texture_First, tc).rgb;\n"
841 "               tc += BloomBlur_Parameters.xy;\n"
842 "       }\n"
843 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
852 "\n"
853 "void main(void)\n"
854 "{\n"
855 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 "       ModelViewProjectionPosition = gl_Position;\n"
858 "}\n"
859 "#endif\n"
860 "\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
865 "\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
873 "\n"
874 "void main(void)\n"
875 "{\n"
876 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 "       // FIXME temporary hack to detect the case that the reflection\n"
881 "       // gets blackened at edges due to leaving the area that contains actual\n"
882 "       // content.\n"
883 "       // Remove this 'ack once we have a better way to stop this thing from\n"
884 "       // 'appening.\n"
885 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
891 "}\n"
892 "#endif\n"
893 "#else // !MODE_REFRACTION\n"
894 "\n"
895 "\n"
896 "\n"
897 "\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
905 "\n"
906 "void main(void)\n"
907 "{\n"
908 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 "       // FIXME temporary hack to detect the case that the reflection\n"
939 "       // gets blackened at edges due to leaving the area that contains actual\n"
940 "       // content.\n"
941 "       // Remove this 'ack once we have a better way to stop this thing from\n"
942 "       // 'appening.\n"
943 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
955 "}\n"
956 "#endif\n"
957 "#else // !MODE_WATER\n"
958 "\n"
959 "\n"
960 "\n"
961 "\n"
962 "// common definitions between vertex shader and fragment shader:\n"
963 "\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
967 "#endif\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
970 "#endif\n"
971 "\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
974 "#endif\n"
975 "\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
982 "#endif\n"
983 "#ifdef USEFOG\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
985 "#endif\n"
986 "\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
991 "#endif\n"
992 "\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
995 "#endif\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1003 "#endif\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1007 "#endif\n"
1008 "uniform vec4 FogPlane;\n"
1009 "\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1012 "#endif\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "\n"
1018 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1019 "\n"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1022 "\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1026 "#ifdef USEGLOW\n"
1027 "uniform sampler2D Texture_Glow;\n"
1028 "#endif\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1033 "#ifdef USEGLOW\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1035 "#endif\n"
1036 "#endif\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1040 "#endif\n"
1041 "#ifdef USEFOG\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1044 "#endif\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1046 "#endif\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1049 "#endif\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1052 "#endif\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1055 "#endif\n"
1056 "\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1060 "#endif\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1064 "#endif\n"
1065 "\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1069 "\n"
1070 "#ifdef USEFOG\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1075 "{\n"
1076 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1078 "       float fogfrac;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 "       fogfrac = fogheightpixel.a;\n"
1082 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1083 "#else\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1086 "# else\n"
1087 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1088 "# endif\n"
1089 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1090 "#endif\n"
1091 "}\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1097 "{\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 "       // 14 sample relief mapping: linear search and then binary search\n"
1100 "       // this basically steps forward a small amount repeatedly until it finds\n"
1101 "       // itself inside solid, then jitters forward and back using decreasing\n"
1102 "       // amounts to find the impact\n"
1103 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 "       vec3 RT = vec3(TexCoord, 1);\n"
1107 "       OffsetVector *= 0.1;\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1118 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1119 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1120 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1121 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1122 "       return RT.xy;\n"
1123 "#else\n"
1124 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 "       // this basically moves forward the full distance, and then backs up based\n"
1126 "       // on height of samples\n"
1127 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 "       TexCoord += OffsetVector;\n"
1131 "       OffsetVector *= 0.333;\n"
1132 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 "       return TexCoord;\n"
1136 "#endif\n"
1137 "}\n"
1138 "#endif // USEOFFSETMAPPING\n"
1139 "\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1143 "#endif\n"
1144 "\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1146 "\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1150 "# else\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1152 "# endif\n"
1153 "#endif\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1157 "#endif\n"
1158 "\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1162 "#endif\n"
1163 "\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1167 "# else\n"
1168 "#  ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1175 "}\n"
1176 "#  else\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 adir = abs(dir);\n"
1180 "       float ma = adir.z;\n"
1181 "       vec4 proj = vec4(dir, 2.5);\n"
1182 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1186 "}\n"
1187 "#  endif\n"
1188 "# endif\n"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1190 "\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1193 "{\n"
1194 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1195 "       float f;\n"
1196 "\n"
1197 "#  ifdef USESHADOWSAMPLER\n"
1198 "#    ifdef USESHADOWMAPPCF\n"
1199 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1200 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1202 "#    else\n"
1203 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1204 "#    endif\n"
1205 "#  else\n"
1206 "#    ifdef USESHADOWMAPPCF\n"
1207 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "#      ifdef GL_ARB_texture_gather\n"
1209 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1210 "#      else\n"
1211 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1212 "#      endif\n"
1213 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "#      if USESHADOWMAPPCF > 1\n"
1215 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1219 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1220 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1221 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1222 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1223 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1224 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 "       locols.yz += group2.ab;\n"
1227 "       hicols.yz += group8.rg;\n"
1228 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 "                               mix(locols, hicols, offset.y);\n"
1231 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 "       f = dot(cols, vec4(1.0/25.0));\n"
1234 "#      else\n"
1235 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1238 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1239 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1242 "#      endif\n"
1243 "#     else\n"
1244 "#      ifdef GL_EXT_gpu_shader4\n"
1245 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1248 "#      endif\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 "       center *= ShadowMap_TextureScale;\n"
1252 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1253 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1254 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1255 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1256 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1258 "#      else\n"
1259 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1262 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1263 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1265 "#      endif\n"
1266 "#     endif\n"
1267 "#    else\n"
1268 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1269 "#    endif\n"
1270 "#  endif\n"
1271 "#  ifdef USESHADOWMAPORTHO\n"
1272 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1273 "#  else\n"
1274 "       return f;\n"
1275 "#  endif\n"
1276 "}\n"
1277 "# endif\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1280 "\n"
1281 "\n"
1282 "\n"
1283 "\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1289 "#endif\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1291 "void main(void)\n"
1292 "{\n"
1293 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 "       gl_FrontColor = gl_Color;\n"
1296 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1297 "#endif\n"
1298 "\n"
1299 "       // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1305 "#endif\n"
1306 "\n"
1307 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1311 "}\n"
1312 "#endif // VERTEX_SHADER\n"
1313 "\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1315 "void main(void)\n"
1316 "{\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 "       // apply offsetmapping\n"
1319 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1321 "#endif\n"
1322 "\n"
1323 "#ifdef USEALPHAKILL\n"
1324 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "               discard;\n"
1326 "#endif\n"
1327 "\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1333 "#endif\n"
1334 "\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1338 "#else\n"
1339 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1341 "#endif\n"
1342 "\n"
1343 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1344 "}\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1347 "\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1354 "void main(void)\n"
1355 "{\n"
1356 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1358 "}\n"
1359 "#endif // VERTEX_SHADER\n"
1360 "\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1370 "#endif\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       // calculate viewspace pixel position\n"
1375 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1376 "       vec3 position;\n"
1377 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 "       // decode viewspace pixel normal\n"
1380 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 "       // surfacenormal = pixel normal in viewspace\n"
1383 "       // LightVector = pixel to light in viewspace\n"
1384 "       // CubeVector = position in lightspace\n"
1385 "       // eyevector = pixel to view in viewspace\n"
1386 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 "       // calculate diffuse shading\n"
1390 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1392 "#endif\n"
1393 "#ifdef USESPECULAR\n"
1394 "       // calculate directional shading\n"
1395 "       vec3 eyevector = position * -1.0;\n"
1396 "#  ifdef USEEXACTSPECULARMATH\n"
1397 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1398 "#  else\n"
1399 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1401 "#  endif\n"
1402 "#endif\n"
1403 "\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 "       fade *= ShadowMapCompare(CubeVector);\n"
1406 "#endif\n"
1407 "\n"
1408 "#ifdef USEDIFFUSE\n"
1409 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1410 "#else\n"
1411 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1412 "#endif\n"
1413 "#ifdef USESPECULAR\n"
1414 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1415 "#else\n"
1416 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1417 "#endif\n"
1418 "\n"
1419 "# ifdef USECUBEFILTER\n"
1420 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 "       gl_FragData[0].rgb *= cubecolor;\n"
1422 "       gl_FragData[1].rgb *= cubecolor;\n"
1423 "# endif\n"
1424 "}\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1427 "\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1435 "#endif\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1438 "#endif\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1441 "#endif\n"
1442 "void main(void)\n"
1443 "{\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 "       gl_FrontColor = gl_Color;\n"
1446 "#endif\n"
1447 "       // copy the surface texcoord\n"
1448 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1451 "#endif\n"
1452 "#ifdef USELIGHTMAP\n"
1453 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "       // transform vertex position into light attenuation/cubemap space\n"
1458 "       // (-1 to +1 across the light box)\n"
1459 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1460 "\n"
1461 "# ifdef USEDIFFUSE\n"
1462 "       // transform unnormalized light direction into tangent space\n"
1463 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 "       //  normalize it per pixel)\n"
1465 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1476 "#endif\n"
1477 "\n"
1478 "       // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef USEFOG\n"
1487 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1489 "#endif\n"
1490 "\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1493 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1494 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1495 "#endif\n"
1496 "\n"
1497 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1499 "\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef USEREFLECTION\n"
1505 "       ModelViewProjectionPosition = gl_Position;\n"
1506 "#endif\n"
1507 "}\n"
1508 "#endif // VERTEX_SHADER\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1518 "#endif\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1523 "#ifdef USEGLOW\n"
1524 "uniform myhalf3 Color_Glow;\n"
1525 "#endif\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1532 "#endif\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1537 "#endif\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1540 "#endif\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1543 "#endif\n"
1544 "void main(void)\n"
1545 "{\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 "       // apply offsetmapping\n"
1548 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1550 "#endif\n"
1551 "\n"
1552 "       // combine the diffuse textures (base, pants, shirt)\n"
1553 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 "       if (color.a < 0.5)\n"
1556 "               discard;\n"
1557 "#endif\n"
1558 "       color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1561 "#endif\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1567 "       color.a = 1.0;\n"
1568 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1569 "#endif\n"
1570 "\n"
1571 "       // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1574 "#else\n"
1575 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1576 "#endif\n"
1577 "\n"
1578 "       // get the material colors\n"
1579 "       myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1583 "# else\n"
1584 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1585 "# endif\n"
1586 "#endif\n"
1587 "\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1593 "#endif\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 "       // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1607 "#else\n"
1608 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1610 "#endif\n"
1611 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1612 "#endif\n"
1613 "#else\n"
1614 "       color.rgb = diffusetex * Color_Ambient;\n"
1615 "#endif\n"
1616 "       color.rgb *= LightColor;\n"
1617 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1620 "#endif\n"
1621 "# ifdef USECUBEFILTER\n"
1622 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1623 "# endif\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1630 "#define SHADING\n"
1631 "#ifdef USEDIFFUSE\n"
1632 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1633 "#endif\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1637 "#define SHADING\n"
1638 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 "       // convert modelspace light vector to tangentspace\n"
1642 "       myhalf3 lightnormal;\n"
1643 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1658 "#define SHADING\n"
1659 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1662 "#endif\n"
1663 "\n"
1664 "\n"
1665 "\n"
1666 "\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 "       color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "\n"
1680 "#ifdef SHADING\n"
1681 "# ifdef USEDIFFUSE\n"
1682 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "#  ifdef USESPECULAR\n"
1684 "#   ifdef USEEXACTSPECULARMATH\n"
1685 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1686 "#   else\n"
1687 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1689 "#   endif\n"
1690 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1691 "#  else\n"
1692 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1693 "#  endif\n"
1694 "# else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "# endif\n"
1697 "#endif\n"
1698 "\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1701 "#endif\n"
1702 "\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1707 "#endif\n"
1708 "\n"
1709 "#ifdef USEGLOW\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1712 "#else\n"
1713 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1714 "#endif\n"
1715 "#endif\n"
1716 "\n"
1717 "#ifdef USEFOG\n"
1718 "       color.rgb = FogVertex(color.rgb);\n"
1719 "#endif\n"
1720 "\n"
1721 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1722 "#ifdef USEREFLECTION\n"
1723 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 "       // FIXME temporary hack to detect the case that the reflection\n"
1728 "       // gets blackened at edges due to leaving the area that contains actual\n"
1729 "       // content.\n"
1730 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1731 "       // 'appening.\n"
1732 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1738 "#endif\n"
1739 "\n"
1740 "       gl_FragColor = vec4(color);\n"
1741 "}\n"
1742 "#endif // FRAGMENT_SHADER\n"
1743 "\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1753 ;
1754
1755 /*
1756 =========================================================================================================================================================
1757
1758
1759
1760 =========================================================================================================================================================
1761
1762
1763
1764 =========================================================================================================================================================
1765
1766
1767
1768 =========================================================================================================================================================
1769
1770
1771
1772 =========================================================================================================================================================
1773
1774
1775
1776 =========================================================================================================================================================
1777
1778
1779
1780 =========================================================================================================================================================
1781 */
1782
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1787 "\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1791 "#endif\n"
1792 "\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1794 "# define USEFOG\n"
1795 "#endif\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1798 "#endif\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1801 "#endif\n"
1802 "\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1804 "#ifdef HLSL\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1808 "#else\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1810 "#endif\n"
1811 "#endif\n"
1812 "\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1815 "void main\n"
1816 "(\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1821 ")\n"
1822 "{\n"
1823 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 "       Depth = gl_Position.z;\n"
1825 "}\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1829 "void main\n"
1830 "(\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1833 ")\n"
1834 "{\n"
1835 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1837 "       temp.yz -= floor(temp.yz);\n"
1838 "       gl_FragColor = temp;\n"
1839 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1840 "}\n"
1841 "#endif\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1843 "\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1849 "void main\n"
1850 "(\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1855 ")\n"
1856 "{\n"
1857 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1859 "}\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1863 "void main\n"
1864 "(\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_FragColor = gl_FrontColor;\n"
1870 "}\n"
1871 "#endif\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1873 "\n"
1874 "\n"
1875 "\n"
1876 "\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1878 "\n"
1879 "#ifdef VERTEX_SHADER\n"
1880 "void main\n"
1881 "(\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1889 ")\n"
1890 "{\n"
1891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1893 "#ifdef USEBLOOM\n"
1894 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1895 "#endif\n"
1896 "}\n"
1897 "#endif\n"
1898 "\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1900 "void main\n"
1901 "(\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1905 "#ifdef USEBLOOM\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1907 "#endif\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1910 "#endif\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1913 "#endif\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1916 "#endif\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1928 "#ifdef USEBLOOM\n"
1929 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1930 "#endif\n"
1931 "#ifdef USEVIEWTINT\n"
1932 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1933 "#endif\n"
1934 "\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1938 "       float sobel = 1.0;\n"
1939 "       // float2 ts = textureSize(Texture_First, 0);\n"
1940 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 "       float2 px = PixelSize;\n"
1942 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1944 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1947 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1950 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1953 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1971 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1972 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1974 "#endif\n"
1975 "\n"
1976 "#ifdef USESATURATION\n"
1977 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1981 "#endif\n"
1982 "\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1987 "#endif\n"
1988 "}\n"
1989 "#endif\n"
1990 "#else // !MODE_POSTPROCESS\n"
1991 "\n"
1992 "\n"
1993 "\n"
1994 "\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1997 "void main\n"
1998 "(\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "#ifdef USEDIFFUSE\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "#endif\n"
2008 "#ifdef USESPECULAR\n"
2009 "out float2 TexCoord2 : TEXCOORD1,\n"
2010 "#endif\n"
2011 "out float4 gl_FrontColor : COLOR\n"
2012 ")\n"
2013 "{\n"
2014 "#ifdef HLSL\n"
2015 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2016 "#else\n"
2017 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2018 "#endif\n"
2019 "#ifdef USEDIFFUSE\n"
2020 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2021 "#endif\n"
2022 "#ifdef USESPECULAR\n"
2023 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2024 "#endif\n"
2025 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2026 "}\n"
2027 "#endif\n"
2028 "\n"
2029 "#ifdef FRAGMENT_SHADER\n"
2030 "\n"
2031 "void main\n"
2032 "(\n"
2033 "float4 gl_FrontColor : COLOR0,\n"
2034 "float2 TexCoord1 : TEXCOORD0,\n"
2035 "float2 TexCoord2 : TEXCOORD1,\n"
2036 "#ifdef USEDIFFUSE\n"
2037 "uniform sampler Texture_First : register(s0),\n"
2038 "#endif\n"
2039 "#ifdef USESPECULAR\n"
2040 "uniform sampler Texture_Second : register(s1),\n"
2041 "#endif\n"
2042 "out float4 gl_FragColor : COLOR\n"
2043 ")\n"
2044 "{\n"
2045 "       gl_FragColor = gl_FrontColor;\n"
2046 "#ifdef USEDIFFUSE\n"
2047 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2048 "#endif\n"
2049 "\n"
2050 "#ifdef USESPECULAR\n"
2051 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2052 "# ifdef USECOLORMAPPING\n"
2053 "       gl_FragColor *= tex2;\n"
2054 "# endif\n"
2055 "# ifdef USEGLOW\n"
2056 "       gl_FragColor += tex2;\n"
2057 "# endif\n"
2058 "# ifdef USEVERTEXTEXTUREBLEND\n"
2059 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2060 "# endif\n"
2061 "#endif\n"
2062 "}\n"
2063 "#endif\n"
2064 "#else // !MODE_GENERIC\n"
2065 "\n"
2066 "\n"
2067 "\n"
2068 "\n"
2069 "#ifdef MODE_BLOOMBLUR\n"
2070 "#ifdef VERTEX_SHADER\n"
2071 "void main\n"
2072 "(\n"
2073 "float4 gl_Vertex : POSITION,\n"
2074 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2075 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2076 "out float4 gl_Position : POSITION,\n"
2077 "out float2 TexCoord : TEXCOORD0\n"
2078 ")\n"
2079 "{\n"
2080 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2081 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2082 "}\n"
2083 "#endif\n"
2084 "\n"
2085 "#ifdef FRAGMENT_SHADER\n"
2086 "\n"
2087 "void main\n"
2088 "(\n"
2089 "float2 TexCoord : TEXCOORD0,\n"
2090 "uniform sampler Texture_First : register(s0),\n"
2091 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2092 "out float4 gl_FragColor : COLOR\n"
2093 ")\n"
2094 "{\n"
2095 "       int i;\n"
2096 "       float2 tc = TexCoord;\n"
2097 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2098 "       tc += BloomBlur_Parameters.xy;\n"
2099 "       for (i = 1;i < SAMPLES;i++)\n"
2100 "       {\n"
2101 "               color += tex2D(Texture_First, tc).rgb;\n"
2102 "               tc += BloomBlur_Parameters.xy;\n"
2103 "       }\n"
2104 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2105 "}\n"
2106 "#endif\n"
2107 "#else // !MODE_BLOOMBLUR\n"
2108 "#ifdef MODE_REFRACTION\n"
2109 "#ifdef VERTEX_SHADER\n"
2110 "void main\n"
2111 "(\n"
2112 "float4 gl_Vertex : POSITION,\n"
2113 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2114 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2115 "uniform float4x4 TexMatrix : register(c0),\n"
2116 "uniform float3 EyePosition : register(c24),\n"
2117 "out float4 gl_Position : POSITION,\n"
2118 "out float2 TexCoord : TEXCOORD0,\n"
2119 "out float3 EyeVector : TEXCOORD1,\n"
2120 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2121 ")\n"
2122 "{\n"
2123 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2124 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2125 "       ModelViewProjectionPosition = gl_Position;\n"
2126 "}\n"
2127 "#endif\n"
2128 "\n"
2129 "#ifdef FRAGMENT_SHADER\n"
2130 "void main\n"
2131 "(\n"
2132 "float2 TexCoord : TEXCOORD0,\n"
2133 "float3 EyeVector : TEXCOORD1,\n"
2134 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2135 "uniform sampler Texture_Normal : register(s0),\n"
2136 "uniform sampler Texture_Refraction : register(s3),\n"
2137 "uniform sampler Texture_Reflection : register(s7),\n"
2138 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2139 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2140 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2141 "uniform float4 RefractColor : register(c29),\n"
2142 "out float4 gl_FragColor : COLOR\n"
2143 ")\n"
2144 "{\n"
2145 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2146 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2147 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2148 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2149 "       // FIXME temporary hack to detect the case that the reflection\n"
2150 "       // gets blackened at edges due to leaving the area that contains actual\n"
2151 "       // content.\n"
2152 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2153 "       // 'appening.\n"
2154 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2155 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2156 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2157 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2158 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2159 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2160 "}\n"
2161 "#endif\n"
2162 "#else // !MODE_REFRACTION\n"
2163 "\n"
2164 "\n"
2165 "\n"
2166 "\n"
2167 "#ifdef MODE_WATER\n"
2168 "#ifdef VERTEX_SHADER\n"
2169 "\n"
2170 "void main\n"
2171 "(\n"
2172 "float4 gl_Vertex : POSITION,\n"
2173 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2174 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2175 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2176 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2177 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2178 "uniform float4x4 TexMatrix : register(c0),\n"
2179 "uniform float3 EyePosition : register(c24),\n"
2180 "out float4 gl_Position : POSITION,\n"
2181 "out float2 TexCoord : TEXCOORD0,\n"
2182 "out float3 EyeVector : TEXCOORD1,\n"
2183 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2184 ")\n"
2185 "{\n"
2186 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2187 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2188 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2189 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2190 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2191 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2192 "       ModelViewProjectionPosition = gl_Position;\n"
2193 "}\n"
2194 "#endif\n"
2195 "\n"
2196 "#ifdef FRAGMENT_SHADER\n"
2197 "void main\n"
2198 "(\n"
2199 "float2 TexCoord : TEXCOORD0,\n"
2200 "float3 EyeVector : TEXCOORD1,\n"
2201 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2202 "uniform sampler Texture_Normal : register(s0),\n"
2203 "uniform sampler Texture_Refraction : register(s3),\n"
2204 "uniform sampler Texture_Reflection : register(s7),\n"
2205 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2206 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2207 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2208 "uniform float4 RefractColor : register(c29),\n"
2209 "uniform float4 ReflectColor : register(c26),\n"
2210 "uniform float ReflectFactor : register(c27),\n"
2211 "uniform float ReflectOffset : register(c28),\n"
2212 "out float4 gl_FragColor : COLOR\n"
2213 ")\n"
2214 "{\n"
2215 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2216 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2217 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2218 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2219 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2220 "       // FIXME temporary hack to detect the case that the reflection\n"
2221 "       // gets blackened at edges due to leaving the area that contains actual\n"
2222 "       // content.\n"
2223 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2224 "       // 'appening.\n"
2225 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2226 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2227 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2228 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2229 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2230 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2231 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2232 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2233 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2234 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2235 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2236 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2237 "}\n"
2238 "#endif\n"
2239 "#else // !MODE_WATER\n"
2240 "\n"
2241 "\n"
2242 "\n"
2243 "\n"
2244 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2245 "\n"
2246 "// fragment shader specific:\n"
2247 "#ifdef FRAGMENT_SHADER\n"
2248 "\n"
2249 "#ifdef USEFOG\n"
2250 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2251 "{\n"
2252 "       float fogfrac;\n"
2253 "#ifdef USEFOGHEIGHTTEXTURE\n"
2254 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2255 "       fogfrac = fogheightpixel.a;\n"
2256 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2257 "#else\n"
2258 "# ifdef USEFOGOUTSIDE\n"
2259 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2260 "# else\n"
2261 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2262 "# endif\n"
2263 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2264 "#endif\n"
2265 "}\n"
2266 "#endif\n"
2267 "\n"
2268 "#ifdef USEOFFSETMAPPING\n"
2269 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2270 "{\n"
2271 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2272 "       // 14 sample relief mapping: linear search and then binary search\n"
2273 "       // this basically steps forward a small amount repeatedly until it finds\n"
2274 "       // itself inside solid, then jitters forward and back using decreasing\n"
2275 "       // amounts to find the impact\n"
2276 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2277 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2278 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2279 "       float3 RT = float3(TexCoord, 1);\n"
2280 "       OffsetVector *= 0.1;\n"
2281 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2287 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2288 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2289 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2290 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2291 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2292 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2293 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2294 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2295 "       return RT.xy;\n"
2296 "#else\n"
2297 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2298 "       // this basically moves forward the full distance, and then backs up based\n"
2299 "       // on height of samples\n"
2300 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2301 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2302 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2303 "       TexCoord += OffsetVector;\n"
2304 "       OffsetVector *= 0.333;\n"
2305 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2306 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2307 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2308 "       return TexCoord;\n"
2309 "#endif\n"
2310 "}\n"
2311 "#endif // USEOFFSETMAPPING\n"
2312 "\n"
2313 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2314 "#if defined(USESHADOWMAP2D)\n"
2315 "# ifdef USESHADOWMAPORTHO\n"
2316 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2317 "# else\n"
2318 "#  ifdef USESHADOWMAPVSDCT\n"
2319 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2320 "{\n"
2321 "       float3 adir = abs(dir);\n"
2322 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2323 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2324 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2325 "}\n"
2326 "#  else\n"
2327 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2328 "{\n"
2329 "       float3 adir = abs(dir);\n"
2330 "       float ma = adir.z;\n"
2331 "       float4 proj = float4(dir, 2.5);\n"
2332 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2333 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2334 "#ifdef HLSL\n"
2335 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2336 "#else\n"
2337 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2338 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2339 "#endif\n"
2340 "}\n"
2341 "#  endif\n"
2342 "# endif\n"
2343 "#endif // defined(USESHADOWMAP2D)\n"
2344 "\n"
2345 "# ifdef USESHADOWMAP2D\n"
2346 "#ifdef USESHADOWMAPVSDCT\n"
2347 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2348 "#else\n"
2349 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2350 "#endif\n"
2351 "{\n"
2352 "#ifdef USESHADOWMAPVSDCT\n"
2353 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2354 "#else\n"
2355 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2356 "#endif\n"
2357 "       float f;\n"
2358 "\n"
2359 "#  ifdef USESHADOWSAMPLER\n"
2360 "#    ifdef USESHADOWMAPPCF\n"
2361 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2362 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2363 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2364 "#    else\n"
2365 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2366 "#    endif\n"
2367 "#  else\n"
2368 "#    ifdef USESHADOWMAPPCF\n"
2369 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2370 "#      ifdef GL_ARB_texture_gather\n"
2371 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2372 "#      else\n"
2373 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2374 "#      endif\n"
2375 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2376 "#      if USESHADOWMAPPCF > 1\n"
2377 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2378 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2379 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2380 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2381 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2382 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2383 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2384 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2385 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2386 "       float4 locols = float4(group1.ab, group3.ab);\n"
2387 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2388 "       locols.yz += group2.ab;\n"
2389 "       hicols.yz += group8.rg;\n"
2390 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2391 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2392 "                               lerp(locols, hicols, offset.y);\n"
2393 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2394 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2395 "       f = dot(cols, float4(1.0/25.0));\n"
2396 "#      else\n"
2397 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2398 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2399 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2400 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2401 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2402 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2403 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2404 "#      endif\n"
2405 "#     else\n"
2406 "#      ifdef GL_EXT_gpu_shader4\n"
2407 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2408 "#      else\n"
2409 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2410 "#      endif\n"
2411 "#      if USESHADOWMAPPCF > 1\n"
2412 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2413 "       center *= ShadowMap_TextureScale;\n"
2414 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2415 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2416 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2417 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2418 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2419 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2420 "#      else\n"
2421 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2422 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2423 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2424 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2425 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2426 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2427 "#      endif\n"
2428 "#     endif\n"
2429 "#    else\n"
2430 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2431 "#    endif\n"
2432 "#  endif\n"
2433 "#  ifdef USESHADOWMAPORTHO\n"
2434 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2435 "#  else\n"
2436 "       return f;\n"
2437 "#  endif\n"
2438 "}\n"
2439 "# endif\n"
2440 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2441 "#endif // FRAGMENT_SHADER\n"
2442 "\n"
2443 "\n"
2444 "\n"
2445 "\n"
2446 "#ifdef MODE_DEFERREDGEOMETRY\n"
2447 "#ifdef VERTEX_SHADER\n"
2448 "void main\n"
2449 "(\n"
2450 "float4 gl_Vertex : POSITION,\n"
2451 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2452 "#ifdef USEVERTEXTEXTUREBLEND\n"
2453 "float4 gl_Color : COLOR0,\n"
2454 "#endif\n"
2455 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2456 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2457 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2458 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2459 "uniform float4x4 TexMatrix : register(c0),\n"
2460 "#ifdef USEVERTEXTEXTUREBLEND\n"
2461 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2462 "#endif\n"
2463 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2464 "#ifdef USEOFFSETMAPPING\n"
2465 "uniform float3 EyePosition : register(c24),\n"
2466 "#endif\n"
2467 "out float4 gl_Position : POSITION,\n"
2468 "#ifdef USEVERTEXTEXTUREBLEND\n"
2469 "out float4 gl_FrontColor : COLOR,\n"
2470 "#endif\n"
2471 "out float4 TexCoordBoth : TEXCOORD0,\n"
2472 "#ifdef USEOFFSETMAPPING\n"
2473 "out float3 EyeVector : TEXCOORD2,\n"
2474 "#endif\n"
2475 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2476 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2477 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2478 ")\n"
2479 "{\n"
2480 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2481 "#ifdef USEVERTEXTEXTUREBLEND\n"
2482 "#ifdef HLSL\n"
2483 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2484 "#else\n"
2485 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2486 "#endif\n"
2487 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2488 "#endif\n"
2489 "\n"
2490 "       // transform unnormalized eye direction into tangent space\n"
2491 "#ifdef USEOFFSETMAPPING\n"
2492 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2493 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2494 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2495 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2496 "#endif\n"
2497 "\n"
2498 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2499 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2500 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2501 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2502 "       VectorR.w = gl_Position.z;\n"
2503 "}\n"
2504 "#endif // VERTEX_SHADER\n"
2505 "\n"
2506 "#ifdef FRAGMENT_SHADER\n"
2507 "void main\n"
2508 "(\n"
2509 "float4 TexCoordBoth : TEXCOORD0,\n"
2510 "float3 EyeVector : TEXCOORD2,\n"
2511 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2512 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2513 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2514 "uniform sampler Texture_Normal : register(s0),\n"
2515 "#ifdef USEALPHAKILL\n"
2516 "uniform sampler Texture_Color : register(s1),\n"
2517 "#endif\n"
2518 "uniform sampler Texture_Gloss : register(s2),\n"
2519 "#ifdef USEVERTEXTEXTUREBLEND\n"
2520 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2521 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2522 "#endif\n"
2523 "#ifdef USEOFFSETMAPPING\n"
2524 "uniform float OffsetMapping_Scale : register(c24),\n"
2525 "#endif\n"
2526 "uniform half SpecularPower : register(c36),\n"
2527 "#ifdef HLSL\n"
2528 "out float4 gl_FragData0 : COLOR0,\n"
2529 "out float4 gl_FragData1 : COLOR1\n"
2530 "#else\n"
2531 "out float4 gl_FragColor : COLOR\n"
2532 "#endif\n"
2533 ")\n"
2534 "{\n"
2535 "       float2 TexCoord = TexCoordBoth.xy;\n"
2536 "#ifdef USEOFFSETMAPPING\n"
2537 "       // apply offsetmapping\n"
2538 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2539 "#define TexCoord TexCoordOffset\n"
2540 "#endif\n"
2541 "\n"
2542 "#ifdef USEALPHAKILL\n"
2543 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2544 "               discard;\n"
2545 "#endif\n"
2546 "\n"
2547 "#ifdef USEVERTEXTEXTUREBLEND\n"
2548 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2549 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2550 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2551 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2552 "#endif\n"
2553 "\n"
2554 "#ifdef USEVERTEXTEXTUREBLEND\n"
2555 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2556 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2557 "#else\n"
2558 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2559 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2560 "#endif\n"
2561 "\n"
2562 "#ifdef HLSL\n"
2563 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2564 "       float Depth = VectorR.w / 256.0;\n"
2565 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2566 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2567 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2568 "       gl_FragData1 = depthcolor;\n"
2569 "#else\n"
2570 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2571 "#endif\n"
2572 "}\n"
2573 "#endif // FRAGMENT_SHADER\n"
2574 "#else // !MODE_DEFERREDGEOMETRY\n"
2575 "\n"
2576 "\n"
2577 "\n"
2578 "\n"
2579 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2580 "#ifdef VERTEX_SHADER\n"
2581 "void main\n"
2582 "(\n"
2583 "float4 gl_Vertex : POSITION,\n"
2584 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2585 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2586 "out float4 gl_Position : POSITION,\n"
2587 "out float4 ModelViewPosition : TEXCOORD0\n"
2588 ")\n"
2589 "{\n"
2590 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2591 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2592 "}\n"
2593 "#endif // VERTEX_SHADER\n"
2594 "\n"
2595 "#ifdef FRAGMENT_SHADER\n"
2596 "void main\n"
2597 "(\n"
2598 "#ifdef HLSL\n"
2599 "float2 Pixel : VPOS,\n"
2600 "#else\n"
2601 "float2 Pixel : WPOS,\n"
2602 "#endif\n"
2603 "float4 ModelViewPosition : TEXCOORD0,\n"
2604 "uniform float4x4 ViewToLight : register(c44),\n"
2605 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2606 "uniform float3 LightPosition : register(c23),\n"
2607 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2608 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2609 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2610 "#ifdef USESPECULAR\n"
2611 "uniform half3 DeferredColor_Specular : register(c11),\n"
2612 "uniform half SpecularPower : register(c36),\n"
2613 "#endif\n"
2614 "uniform sampler Texture_Attenuation : register(s9),\n"
2615 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2616 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2617 "\n"
2618 "#ifdef USECUBEFILTER\n"
2619 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2620 "#endif\n"
2621 "\n"
2622 "#ifdef USESHADOWMAP2D\n"
2623 "# ifdef USESHADOWSAMPLER\n"
2624 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2625 "# else\n"
2626 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2627 "# endif\n"
2628 "#endif\n"
2629 "\n"
2630 "#ifdef USESHADOWMAPVSDCT\n"
2631 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2632 "#endif\n"
2633 "\n"
2634 "#if defined(USESHADOWMAP2D)\n"
2635 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2636 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2637 "#endif\n"
2638 "\n"
2639 "out float4 gl_FragData0 : COLOR0,\n"
2640 "out float4 gl_FragData1 : COLOR1\n"
2641 ")\n"
2642 "{\n"
2643 "       // calculate viewspace pixel position\n"
2644 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2645 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2646 "       float3 position;\n"
2647 "#ifdef HLSL\n"
2648 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2649 "#else\n"
2650 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2651 "#endif\n"
2652 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2653 "       // decode viewspace pixel normal\n"
2654 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2655 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2656 "       // surfacenormal = pixel normal in viewspace\n"
2657 "       // LightVector = pixel to light in viewspace\n"
2658 "       // CubeVector = position in lightspace\n"
2659 "       // eyevector = pixel to view in viewspace\n"
2660 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2661 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2662 "#ifdef USEDIFFUSE\n"
2663 "       // calculate diffuse shading\n"
2664 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2665 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2666 "#endif\n"
2667 "#ifdef USESPECULAR\n"
2668 "       // calculate directional shading\n"
2669 "       float3 eyevector = position * -1.0;\n"
2670 "#  ifdef USEEXACTSPECULARMATH\n"
2671 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2672 "#  else\n"
2673 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2674 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2675 "#  endif\n"
2676 "#endif\n"
2677 "\n"
2678 "#if defined(USESHADOWMAP2D)\n"
2679 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2680 "#ifdef USESHADOWMAPVSDCT\n"
2681 ", Texture_CubeProjection\n"
2682 "#endif\n"
2683 "       ));\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef USEDIFFUSE\n"
2687 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2688 "#else\n"
2689 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2690 "#endif\n"
2691 "#ifdef USESPECULAR\n"
2692 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2693 "#else\n"
2694 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2695 "#endif\n"
2696 "\n"
2697 "# ifdef USECUBEFILTER\n"
2698 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2699 "       gl_FragData0.rgb *= cubecolor;\n"
2700 "       gl_FragData1.rgb *= cubecolor;\n"
2701 "# endif\n"
2702 "}\n"
2703 "#endif // FRAGMENT_SHADER\n"
2704 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2705 "\n"
2706 "\n"
2707 "\n"
2708 "\n"
2709 "#ifdef VERTEX_SHADER\n"
2710 "void main\n"
2711 "(\n"
2712 "float4 gl_Vertex : POSITION,\n"
2713 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2714 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2715 "float4 gl_Color : COLOR0,\n"
2716 "#endif\n"
2717 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2718 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2719 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2720 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2721 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2722 "\n"
2723 "uniform float3 EyePosition : register(c24),\n"
2724 "uniform float4x4 TexMatrix : register(c0),\n"
2725 "#ifdef USEVERTEXTEXTUREBLEND\n"
2726 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2727 "#endif\n"
2728 "#ifdef MODE_LIGHTSOURCE\n"
2729 "uniform float4x4 ModelToLight : register(c20),\n"
2730 "#endif\n"
2731 "#ifdef MODE_LIGHTSOURCE\n"
2732 "uniform float3 LightPosition : register(c27),\n"
2733 "#endif\n"
2734 "#ifdef MODE_LIGHTDIRECTION\n"
2735 "uniform float3 LightDir : register(c26),\n"
2736 "#endif\n"
2737 "uniform float4 FogPlane : register(c25),\n"
2738 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2739 "uniform float3 LightPosition : register(c27),\n"
2740 "#endif\n"
2741 "#ifdef USESHADOWMAPORTHO\n"
2742 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2743 "#endif\n"
2744 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2745 "out float4 gl_FrontColor : COLOR,\n"
2746 "#endif\n"
2747 "out float4 TexCoordBoth : TEXCOORD0,\n"
2748 "#ifdef USELIGHTMAP\n"
2749 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2750 "#endif\n"
2751 "#ifdef USEEYEVECTOR\n"
2752 "out float3 EyeVector : TEXCOORD2,\n"
2753 "#endif\n"
2754 "#ifdef USEREFLECTION\n"
2755 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2756 "#endif\n"
2757 "#ifdef USEFOG\n"
2758 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2759 "#endif\n"
2760 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2761 "out float3 LightVector : TEXCOORD1,\n"
2762 "#endif\n"
2763 "#ifdef MODE_LIGHTSOURCE\n"
2764 "out float3 CubeVector : TEXCOORD3,\n"
2765 "#endif\n"
2766 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2767 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2768 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2769 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2770 "#endif\n"
2771 "#ifdef USESHADOWMAPORTHO\n"
2772 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2773 "#endif\n"
2774 "out float4 gl_Position : POSITION\n"
2775 ")\n"
2776 "{\n"
2777 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2778 "#ifdef HLSL\n"
2779 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2780 "#else\n"
2781 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2782 "#endif\n"
2783 "#endif\n"
2784 "       // copy the surface texcoord\n"
2785 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2786 "#ifdef USEVERTEXTEXTUREBLEND\n"
2787 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2788 "#endif\n"
2789 "#ifdef USELIGHTMAP\n"
2790 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2791 "#endif\n"
2792 "\n"
2793 "#ifdef MODE_LIGHTSOURCE\n"
2794 "       // transform vertex position into light attenuation/cubemap space\n"
2795 "       // (-1 to +1 across the light box)\n"
2796 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2797 "\n"
2798 "# ifdef USEDIFFUSE\n"
2799 "       // transform unnormalized light direction into tangent space\n"
2800 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2801 "       //  normalize it per pixel)\n"
2802 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2803 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2804 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2805 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2806 "# endif\n"
2807 "#endif\n"
2808 "\n"
2809 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2810 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2811 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2812 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2813 "#endif\n"
2814 "\n"
2815 "       // transform unnormalized eye direction into tangent space\n"
2816 "#ifdef USEEYEVECTOR\n"
2817 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2818 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2819 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2820 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2821 "#endif\n"
2822 "\n"
2823 "#ifdef USEFOG\n"
2824 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2825 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2826 "#endif\n"
2827 "\n"
2828 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2829 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2830 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2831 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2832 "#endif\n"
2833 "\n"
2834 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2835 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2836 "\n"
2837 "#ifdef USESHADOWMAPORTHO\n"
2838 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2839 "#endif\n"
2840 "\n"
2841 "#ifdef USEREFLECTION\n"
2842 "       ModelViewProjectionPosition = gl_Position;\n"
2843 "#endif\n"
2844 "}\n"
2845 "#endif // VERTEX_SHADER\n"
2846 "\n"
2847 "\n"
2848 "\n"
2849 "\n"
2850 "#ifdef FRAGMENT_SHADER\n"
2851 "void main\n"
2852 "(\n"
2853 "#ifdef USEDEFERREDLIGHTMAP\n"
2854 "#ifdef HLSL\n"
2855 "float2 Pixel : VPOS,\n"
2856 "#else\n"
2857 "float2 Pixel : WPOS,\n"
2858 "#endif\n"
2859 "#endif\n"
2860 "float4 gl_FrontColor : COLOR,\n"
2861 "float4 TexCoordBoth : TEXCOORD0,\n"
2862 "#ifdef USELIGHTMAP\n"
2863 "float2 TexCoordLightmap : TEXCOORD1,\n"
2864 "#endif\n"
2865 "#ifdef USEEYEVECTOR\n"
2866 "float3 EyeVector : TEXCOORD2,\n"
2867 "#endif\n"
2868 "#ifdef USEREFLECTION\n"
2869 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2870 "#endif\n"
2871 "#ifdef USEFOG\n"
2872 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2873 "#endif\n"
2874 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2875 "float3 LightVector : TEXCOORD1,\n"
2876 "#endif\n"
2877 "#ifdef MODE_LIGHTSOURCE\n"
2878 "float3 CubeVector : TEXCOORD3,\n"
2879 "#endif\n"
2880 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2881 "float4 ModelViewPosition : TEXCOORD0,\n"
2882 "#endif\n"
2883 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2884 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2885 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2886 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2887 "#endif\n"
2888 "#ifdef USESHADOWMAPORTHO\n"
2889 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2890 "#endif\n"
2891 "\n"
2892 "uniform sampler Texture_Normal : register(s0),\n"
2893 "uniform sampler Texture_Color : register(s1),\n"
2894 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2895 "uniform sampler Texture_Gloss : register(s2),\n"
2896 "#endif\n"
2897 "#ifdef USEGLOW\n"
2898 "uniform sampler Texture_Glow : register(s3),\n"
2899 "#endif\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2902 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2903 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2904 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2905 "#endif\n"
2906 "#ifdef USEGLOW\n"
2907 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2908 "#endif\n"
2909 "#endif\n"
2910 "#ifdef USECOLORMAPPING\n"
2911 "uniform sampler Texture_Pants : register(s4),\n"
2912 "uniform sampler Texture_Shirt : register(s7),\n"
2913 "#endif\n"
2914 "#ifdef USEFOG\n"
2915 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2916 "uniform sampler Texture_FogMask : register(s8),\n"
2917 "#endif\n"
2918 "#ifdef USELIGHTMAP\n"
2919 "uniform sampler Texture_Lightmap : register(s9),\n"
2920 "#endif\n"
2921 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2922 "uniform sampler Texture_Deluxemap : register(s10),\n"
2923 "#endif\n"
2924 "#ifdef USEREFLECTION\n"
2925 "uniform sampler Texture_Reflection : register(s7),\n"
2926 "#endif\n"
2927 "\n"
2928 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2929 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2930 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2931 "#endif\n"
2932 "#ifdef USEDEFERREDLIGHTMAP\n"
2933 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2934 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2935 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2936 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2937 "#endif\n"
2938 "\n"
2939 "#ifdef USECOLORMAPPING\n"
2940 "uniform half3 Color_Pants : register(c7),\n"
2941 "uniform half3 Color_Shirt : register(c8),\n"
2942 "#endif\n"
2943 "#ifdef USEFOG\n"
2944 "uniform float3 FogColor : register(c16),\n"
2945 "uniform float FogRangeRecip : register(c20),\n"
2946 "uniform float FogPlaneViewDist : register(c19),\n"
2947 "uniform float FogHeightFade : register(c17),\n"
2948 "#endif\n"
2949 "\n"
2950 "#ifdef USEOFFSETMAPPING\n"
2951 "uniform float OffsetMapping_Scale : register(c24),\n"
2952 "#endif\n"
2953 "\n"
2954 "#ifdef USEDEFERREDLIGHTMAP\n"
2955 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2956 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2957 "uniform half3 DeferredMod_Specular : register(c13),\n"
2958 "#endif\n"
2959 "uniform half3 Color_Ambient : register(c3),\n"
2960 "uniform half3 Color_Diffuse : register(c4),\n"
2961 "uniform half3 Color_Specular : register(c5),\n"
2962 "uniform half SpecularPower : register(c36),\n"
2963 "#ifdef USEGLOW\n"
2964 "uniform half3 Color_Glow : register(c6),\n"
2965 "#endif\n"
2966 "uniform half Alpha : register(c0),\n"
2967 "#ifdef USEREFLECTION\n"
2968 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2969 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2970 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2971 "uniform half4 ReflectColor : register(c26),\n"
2972 "#endif\n"
2973 "#ifdef USEREFLECTCUBE\n"
2974 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2975 "uniform sampler Texture_ReflectMask : register(s5),\n"
2976 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2977 "#endif\n"
2978 "#ifdef MODE_LIGHTDIRECTION\n"
2979 "uniform half3 LightColor : register(c21),\n"
2980 "#endif\n"
2981 "#ifdef MODE_LIGHTSOURCE\n"
2982 "uniform half3 LightColor : register(c21),\n"
2983 "#endif\n"
2984 "\n"
2985 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2986 "uniform sampler Texture_Attenuation : register(s9),\n"
2987 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2988 "#endif\n"
2989 "\n"
2990 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2991 "\n"
2992 "#ifdef USESHADOWMAP2D\n"
2993 "# ifdef USESHADOWSAMPLER\n"
2994 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2995 "# else\n"
2996 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2997 "# endif\n"
2998 "#endif\n"
2999 "\n"
3000 "#ifdef USESHADOWMAPVSDCT\n"
3001 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3002 "#endif\n"
3003 "\n"
3004 "#if defined(USESHADOWMAP2D)\n"
3005 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3006 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3007 "#endif\n"
3008 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3009 "\n"
3010 "out float4 gl_FragColor : COLOR\n"
3011 ")\n"
3012 "{\n"
3013 "       float2 TexCoord = TexCoordBoth.xy;\n"
3014 "#ifdef USEVERTEXTEXTUREBLEND\n"
3015 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3016 "#endif\n"
3017 "#ifdef USEOFFSETMAPPING\n"
3018 "       // apply offsetmapping\n"
3019 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3020 "#define TexCoord TexCoordOffset\n"
3021 "#endif\n"
3022 "\n"
3023 "       // combine the diffuse textures (base, pants, shirt)\n"
3024 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3025 "#ifdef USEALPHAKILL\n"
3026 "       if (color.a < 0.5)\n"
3027 "               discard;\n"
3028 "#endif\n"
3029 "       color.a *= Alpha;\n"
3030 "#ifdef USECOLORMAPPING\n"
3031 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3032 "#endif\n"
3033 "#ifdef USEVERTEXTEXTUREBLEND\n"
3034 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3035 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3036 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3037 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3038 "       color.a = 1.0;\n"
3039 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3040 "#endif\n"
3041 "\n"
3042 "       // get the surface normal\n"
3043 "#ifdef USEVERTEXTEXTUREBLEND\n"
3044 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3045 "#else\n"
3046 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3047 "#endif\n"
3048 "\n"
3049 "       // get the material colors\n"
3050 "       half3 diffusetex = color.rgb;\n"
3051 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3052 "# ifdef USEVERTEXTEXTUREBLEND\n"
3053 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3054 "# else\n"
3055 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3056 "# endif\n"
3057 "#endif\n"
3058 "\n"
3059 "#ifdef USEREFLECTCUBE\n"
3060 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3061 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3062 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3063 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3064 "#endif\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "\n"
3069 "#ifdef MODE_LIGHTSOURCE\n"
3070 "       // light source\n"
3071 "#ifdef USEDIFFUSE\n"
3072 "       half3 lightnormal = half3(normalize(LightVector));\n"
3073 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3074 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3075 "#ifdef USESPECULAR\n"
3076 "#ifdef USEEXACTSPECULARMATH\n"
3077 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3078 "#else\n"
3079 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3080 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3081 "#endif\n"
3082 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3083 "#endif\n"
3084 "#else\n"
3085 "       color.rgb = diffusetex * Color_Ambient;\n"
3086 "#endif\n"
3087 "       color.rgb *= LightColor;\n"
3088 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3089 "#if defined(USESHADOWMAP2D)\n"
3090 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3091 "#ifdef USESHADOWMAPVSDCT\n"
3092 ", Texture_CubeProjection\n"
3093 "#endif\n"
3094 "       ));\n"
3095 "\n"
3096 "#endif\n"
3097 "# ifdef USECUBEFILTER\n"
3098 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3099 "# endif\n"
3100 "\n"
3101 "#ifdef USESHADOWMAP2D\n"
3102 "#ifdef USESHADOWMAPVSDCT\n"
3103 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3104 "#else\n"
3105 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3106 "#endif\n"
3107 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3108 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3109 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3110 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3111 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3112 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3113 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3114 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3115 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3116 "//     color.r = half(shadowmaptc.z);\n"
3117 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3118 "//     color.r = half(shadowmaptc.z);\n"
3119 "//     color.r = 1;\n"
3120 "//     color.rgb = abs(CubeVector);\n"
3121 "#endif\n"
3122 "//     color.rgb = half3(1,1,1);\n"
3123 "#endif // MODE_LIGHTSOURCE\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "\n"
3128 "#ifdef MODE_LIGHTDIRECTION\n"
3129 "#define SHADING\n"
3130 "#ifdef USEDIFFUSE\n"
3131 "       half3 lightnormal = half3(normalize(LightVector));\n"
3132 "#endif\n"
3133 "#define lightcolor LightColor\n"
3134 "#endif // MODE_LIGHTDIRECTION\n"
3135 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3136 "#define SHADING\n"
3137 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3138 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3139 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3140 "       // convert modelspace light vector to tangentspace\n"
3141 "       half3 lightnormal;\n"
3142 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3143 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3144 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3145 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3146 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3147 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3148 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3149 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3150 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3151 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3152 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3153 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3154 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3155 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3156 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3157 "#define SHADING\n"
3158 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3159 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3160 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3161 "#endif\n"
3162 "\n"
3163 "\n"
3164 "\n"
3165 "\n"
3166 "#ifdef MODE_LIGHTMAP\n"
3167 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3168 "#endif // MODE_LIGHTMAP\n"
3169 "#ifdef MODE_VERTEXCOLOR\n"
3170 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3171 "#endif // MODE_VERTEXCOLOR\n"
3172 "#ifdef MODE_FLATCOLOR\n"
3173 "       color.rgb = diffusetex * Color_Ambient;\n"
3174 "#endif // MODE_FLATCOLOR\n"
3175 "\n"
3176 "\n"
3177 "\n"
3178 "\n"
3179 "#ifdef SHADING\n"
3180 "# ifdef USEDIFFUSE\n"
3181 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3182 "#  ifdef USESPECULAR\n"
3183 "#   ifdef USEEXACTSPECULARMATH\n"
3184 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3185 "#   else\n"
3186 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3187 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3188 "#   endif\n"
3189 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3190 "#  else\n"
3191 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3192 "#  endif\n"
3193 "# else\n"
3194 "       color.rgb = diffusetex * Color_Ambient;\n"
3195 "# endif\n"
3196 "#endif\n"
3197 "\n"
3198 "#ifdef USESHADOWMAPORTHO\n"
3199 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3200 "#endif\n"
3201 "\n"
3202 "#ifdef USEDEFERREDLIGHTMAP\n"
3203 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3204 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3205 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3206 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3207 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3208 "#endif\n"
3209 "\n"
3210 "#ifdef USEGLOW\n"
3211 "#ifdef USEVERTEXTEXTUREBLEND\n"
3212 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3213 "#else\n"
3214 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3215 "#endif\n"
3216 "#endif\n"
3217 "\n"
3218 "#ifdef USEFOG\n"
3219 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3220 "#endif\n"
3221 "\n"
3222 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3223 "#ifdef USEREFLECTION\n"
3224 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3225 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3226 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3227 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3228 "       // FIXME temporary hack to detect the case that the reflection\n"
3229 "       // gets blackened at edges due to leaving the area that contains actual\n"
3230 "       // content.\n"
3231 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3232 "       // 'appening.\n"
3233 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3234 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3235 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3236 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3237 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3238 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3239 "#endif\n"
3240 "\n"
3241 "       gl_FragColor = float4(color);\n"
3242 "}\n"
3243 "#endif // FRAGMENT_SHADER\n"
3244 "\n"
3245 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3246 "#endif // !MODE_DEFERREDGEOMETRY\n"
3247 "#endif // !MODE_WATER\n"
3248 "#endif // !MODE_REFRACTION\n"
3249 "#endif // !MODE_BLOOMBLUR\n"
3250 "#endif // !MODE_GENERIC\n"
3251 "#endif // !MODE_POSTPROCESS\n"
3252 "#endif // !MODE_SHOWDEPTH\n"
3253 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3254 ;
3255
3256 char *glslshaderstring = NULL;
3257 char *cgshaderstring = NULL;
3258 char *hlslshaderstring = NULL;
3259
3260 //=======================================================================================================================================================
3261
3262 typedef struct shaderpermutationinfo_s
3263 {
3264         const char *pretext;
3265         const char *name;
3266 }
3267 shaderpermutationinfo_t;
3268
3269 typedef struct shadermodeinfo_s
3270 {
3271         const char *vertexfilename;
3272         const char *geometryfilename;
3273         const char *fragmentfilename;
3274         const char *pretext;
3275         const char *name;
3276 }
3277 shadermodeinfo_t;
3278
3279 typedef enum shaderpermutation_e
3280 {
3281         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3282         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3283         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3284         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3285         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3286         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3287         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3288         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3289         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3290         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3291         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3292         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3293         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3294         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3295         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3296         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3297         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3298         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3299         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3300         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3301         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3302         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3303         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3304         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3305         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3306         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3307         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3308         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3309         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3310 }
3311 shaderpermutation_t;
3312
3313 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3314 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3315 {
3316         {"#define USEDIFFUSE\n", " diffuse"},
3317         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3318         {"#define USEVIEWTINT\n", " viewtint"},
3319         {"#define USECOLORMAPPING\n", " colormapping"},
3320         {"#define USESATURATION\n", " saturation"},
3321         {"#define USEFOGINSIDE\n", " foginside"},
3322         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3323         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3324         {"#define USEGAMMARAMPS\n", " gammaramps"},
3325         {"#define USECUBEFILTER\n", " cubefilter"},
3326         {"#define USEGLOW\n", " glow"},
3327         {"#define USEBLOOM\n", " bloom"},
3328         {"#define USESPECULAR\n", " specular"},
3329         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3330         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3331         {"#define USEREFLECTION\n", " reflection"},
3332         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3333         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3334         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3335         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3336         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3337         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3338         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3339         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3340         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3341         {"#define USEALPHAKILL\n", " alphakill"},
3342         {"#define USEREFLECTCUBE\n", " reflectcube"},
3343 };
3344
3345 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3346 typedef enum shadermode_e
3347 {
3348         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3349         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3350         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3351         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3352         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3353         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3354         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3355         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3356         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3357         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3358         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3359         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3360         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3361         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3362         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3363         SHADERMODE_COUNT
3364 }
3365 shadermode_t;
3366
3367 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3368 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3369 {
3370         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3371         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3372         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3373         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3374         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3375         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3376         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3377         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3378         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3379         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3380         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3381         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3382         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3383         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3384         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3385 };
3386
3387 #ifdef SUPPORTCG
3388 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3389 {
3390         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3391         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3392         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3393         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3394         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3395         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3396         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3397         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3398         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3399         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3400         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3401         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3402         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3403         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3404         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3405 };
3406 #endif
3407
3408 #ifdef SUPPORTD3D
3409 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3410 {
3411         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3412         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3413         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3414         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3415         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3416         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3417         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3418         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3419         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3420         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3421         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3422         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3423         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3426 };
3427 #endif
3428
3429 struct r_glsl_permutation_s;
3430 typedef struct r_glsl_permutation_s
3431 {
3432         /// hash lookup data
3433         struct r_glsl_permutation_s *hashnext;
3434         unsigned int mode;
3435         unsigned int permutation;
3436
3437         /// indicates if we have tried compiling this permutation already
3438         qboolean compiled;
3439         /// 0 if compilation failed
3440         int program;
3441         /// locations of detected uniforms in program object, or -1 if not found
3442         int loc_Texture_First;
3443         int loc_Texture_Second;
3444         int loc_Texture_GammaRamps;
3445         int loc_Texture_Normal;
3446         int loc_Texture_Color;
3447         int loc_Texture_Gloss;
3448         int loc_Texture_Glow;
3449         int loc_Texture_SecondaryNormal;
3450         int loc_Texture_SecondaryColor;
3451         int loc_Texture_SecondaryGloss;
3452         int loc_Texture_SecondaryGlow;
3453         int loc_Texture_Pants;
3454         int loc_Texture_Shirt;
3455         int loc_Texture_FogHeightTexture;
3456         int loc_Texture_FogMask;
3457         int loc_Texture_Lightmap;
3458         int loc_Texture_Deluxemap;
3459         int loc_Texture_Attenuation;
3460         int loc_Texture_Cube;
3461         int loc_Texture_Refraction;
3462         int loc_Texture_Reflection;
3463         int loc_Texture_ShadowMap2D;
3464         int loc_Texture_CubeProjection;
3465         int loc_Texture_ScreenDepth;
3466         int loc_Texture_ScreenNormalMap;
3467         int loc_Texture_ScreenDiffuse;
3468         int loc_Texture_ScreenSpecular;
3469         int loc_Texture_ReflectMask;
3470         int loc_Texture_ReflectCube;
3471         int loc_Alpha;
3472         int loc_BloomBlur_Parameters;
3473         int loc_ClientTime;
3474         int loc_Color_Ambient;
3475         int loc_Color_Diffuse;
3476         int loc_Color_Specular;
3477         int loc_Color_Glow;
3478         int loc_Color_Pants;
3479         int loc_Color_Shirt;
3480         int loc_DeferredColor_Ambient;
3481         int loc_DeferredColor_Diffuse;
3482         int loc_DeferredColor_Specular;
3483         int loc_DeferredMod_Diffuse;
3484         int loc_DeferredMod_Specular;
3485         int loc_DistortScaleRefractReflect;
3486         int loc_EyePosition;
3487         int loc_FogColor;
3488         int loc_FogHeightFade;
3489         int loc_FogPlane;
3490         int loc_FogPlaneViewDist;
3491         int loc_FogRangeRecip;
3492         int loc_LightColor;
3493         int loc_LightDir;
3494         int loc_LightPosition;
3495         int loc_OffsetMapping_Scale;
3496         int loc_PixelSize;
3497         int loc_ReflectColor;
3498         int loc_ReflectFactor;
3499         int loc_ReflectOffset;
3500         int loc_RefractColor;
3501         int loc_Saturation;
3502         int loc_ScreenCenterRefractReflect;
3503         int loc_ScreenScaleRefractReflect;
3504         int loc_ScreenToDepth;
3505         int loc_ShadowMap_Parameters;
3506         int loc_ShadowMap_TextureScale;
3507         int loc_SpecularPower;
3508         int loc_UserVec1;
3509         int loc_UserVec2;
3510         int loc_UserVec3;
3511         int loc_UserVec4;
3512         int loc_ViewTintColor;
3513         int loc_ViewToLight;
3514         int loc_ModelToLight;
3515         int loc_TexMatrix;
3516         int loc_BackgroundTexMatrix;
3517         int loc_ModelViewProjectionMatrix;
3518         int loc_ModelViewMatrix;
3519         int loc_PixelToScreenTexCoord;
3520         int loc_ModelToReflectCube;
3521         int loc_ShadowMapMatrix;
3522         int loc_BloomColorSubtract;
3523 }
3524 r_glsl_permutation_t;
3525
3526 #define SHADERPERMUTATION_HASHSIZE 256
3527
3528 /// information about each possible shader permutation
3529 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3530 /// currently selected permutation
3531 r_glsl_permutation_t *r_glsl_permutation;
3532 /// storage for permutations linked in the hash table
3533 memexpandablearray_t r_glsl_permutationarray;
3534
3535 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3536 {
3537         //unsigned int hashdepth = 0;
3538         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3539         r_glsl_permutation_t *p;
3540         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3541         {
3542                 if (p->mode == mode && p->permutation == permutation)
3543                 {
3544                         //if (hashdepth > 10)
3545                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3546                         return p;
3547                 }
3548                 //hashdepth++;
3549         }
3550         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3551         p->mode = mode;
3552         p->permutation = permutation;
3553         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3554         r_glsl_permutationhash[mode][hashindex] = p;
3555         //if (hashdepth > 10)
3556         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3557         return p;
3558 }
3559
3560 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3561 {
3562         char *shaderstring;
3563         if (!filename || !filename[0])
3564                 return NULL;
3565         if (!strcmp(filename, "glsl/default.glsl"))
3566         {
3567                 if (!glslshaderstring)
3568                 {
3569                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3570                         if (glslshaderstring)
3571                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3572                         else
3573                                 glslshaderstring = (char *)builtinshaderstring;
3574                 }
3575                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3576                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3577                 return shaderstring;
3578         }
3579         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3580         if (shaderstring)
3581         {
3582                 if (printfromdisknotice)
3583                         Con_DPrintf("from disk %s... ", filename);
3584                 return shaderstring;
3585         }
3586         return shaderstring;
3587 }
3588
3589 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3590 {
3591         int i;
3592         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3593         int vertstrings_count = 0;
3594         int geomstrings_count = 0;
3595         int fragstrings_count = 0;
3596         char *vertexstring, *geometrystring, *fragmentstring;
3597         const char *vertstrings_list[32+3];
3598         const char *geomstrings_list[32+3];
3599         const char *fragstrings_list[32+3];
3600         char permutationname[256];
3601
3602         if (p->compiled)
3603                 return;
3604         p->compiled = true;
3605         p->program = 0;
3606
3607         permutationname[0] = 0;
3608         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3609         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3610         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3611
3612         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3613
3614         // the first pretext is which type of shader to compile as
3615         // (later these will all be bound together as a program object)
3616         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3617         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3618         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3619
3620         // the second pretext is the mode (for example a light source)
3621         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3622         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3623         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3624         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3625
3626         // now add all the permutation pretexts
3627         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3628         {
3629                 if (permutation & (1<<i))
3630                 {
3631                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3632                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3633                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3634                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3635                 }
3636                 else
3637                 {
3638                         // keep line numbers correct
3639                         vertstrings_list[vertstrings_count++] = "\n";
3640                         geomstrings_list[geomstrings_count++] = "\n";
3641                         fragstrings_list[fragstrings_count++] = "\n";
3642                 }
3643         }
3644
3645         // now append the shader text itself
3646         vertstrings_list[vertstrings_count++] = vertexstring;
3647         geomstrings_list[geomstrings_count++] = geometrystring;
3648         fragstrings_list[fragstrings_count++] = fragmentstring;
3649
3650         // if any sources were NULL, clear the respective list
3651         if (!vertexstring)
3652                 vertstrings_count = 0;
3653         if (!geometrystring)
3654                 geomstrings_count = 0;
3655         if (!fragmentstring)
3656                 fragstrings_count = 0;
3657
3658         // compile the shader program
3659         if (vertstrings_count + geomstrings_count + fragstrings_count)
3660                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3661         if (p->program)
3662         {
3663                 CHECKGLERROR
3664                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3665                 // look up all the uniform variable names we care about, so we don't
3666                 // have to look them up every time we set them
3667
3668                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3669                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3670                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3671                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3672                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3673                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3674                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3675                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3676                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3677                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3678                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3679                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3680                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3681                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3682                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3683                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3684                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3685                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3686                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3687                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3688                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3689                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3690                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3691                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3692                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3693                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3694                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3695                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3696                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3697                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3698                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3699                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3700                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3701                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3702                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3703                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3704                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3705                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3706                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3707                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3708                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3709                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3710                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3711                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3712                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3713                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3714                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3715                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3716                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3717                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3718                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3719                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3720                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3721                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3722                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3723                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3724                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3725                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3726                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3727                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3728                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3729                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3730                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3731                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3732                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3733                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3734                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3735                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3736                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3737                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3738                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3739                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3740                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3741                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3742                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3743                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3744                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3745                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3746                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3747                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3748                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3749                 // initialize the samplers to refer to the texture units we use
3750                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3751                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3752                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3753                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3754                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3755                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3756                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3757                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3758                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3759                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3760                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3761                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3762                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3763                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3764                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3765                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3766                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3767                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3768                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3769                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3770                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3771                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3772                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3773                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3774                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3775                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3776                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3777                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3778                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3779                 CHECKGLERROR
3780                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3781         }
3782         else
3783                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3784
3785         // free the strings
3786         if (vertexstring)
3787                 Mem_Free(vertexstring);
3788         if (geometrystring)
3789                 Mem_Free(geometrystring);
3790         if (fragmentstring)
3791                 Mem_Free(fragmentstring);
3792 }
3793
3794 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3795 {
3796         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3797         if (r_glsl_permutation != perm)
3798         {
3799                 r_glsl_permutation = perm;
3800                 if (!r_glsl_permutation->program)
3801                 {
3802                         if (!r_glsl_permutation->compiled)
3803                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3804                         if (!r_glsl_permutation->program)
3805                         {
3806                                 // remove features until we find a valid permutation
3807                                 int i;
3808                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3809                                 {
3810                                         // reduce i more quickly whenever it would not remove any bits
3811                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3812                                         if (!(permutation & j))
3813                                                 continue;
3814                                         permutation -= j;
3815                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3816                                         if (!r_glsl_permutation->compiled)
3817                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3818                                         if (r_glsl_permutation->program)
3819                                                 break;
3820                                 }
3821                                 if (i >= SHADERPERMUTATION_COUNT)
3822                                 {
3823                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3824                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3825                                         qglUseProgramObjectARB(0);CHECKGLERROR
3826                                         return; // no bit left to clear, entire mode is broken
3827                                 }
3828                         }
3829                 }
3830                 CHECKGLERROR
3831                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3832         }
3833         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3834         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3835         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3836 }
3837
3838 #ifdef SUPPORTCG
3839 #include <Cg/cgGL.h>
3840 struct r_cg_permutation_s;
3841 typedef struct r_cg_permutation_s
3842 {
3843         /// hash lookup data
3844         struct r_cg_permutation_s *hashnext;
3845         unsigned int mode;
3846         unsigned int permutation;
3847
3848         /// indicates if we have tried compiling this permutation already
3849         qboolean compiled;
3850         /// 0 if compilation failed
3851         CGprogram vprogram;
3852         CGprogram fprogram;
3853         /// locations of detected parameters in programs, or NULL if not found
3854         CGparameter vp_EyePosition;
3855         CGparameter vp_FogPlane;
3856         CGparameter vp_LightDir;
3857         CGparameter vp_LightPosition;
3858         CGparameter vp_ModelToLight;
3859         CGparameter vp_TexMatrix;
3860         CGparameter vp_BackgroundTexMatrix;
3861         CGparameter vp_ModelViewProjectionMatrix;
3862         CGparameter vp_ModelViewMatrix;
3863         CGparameter vp_ShadowMapMatrix;
3864
3865         CGparameter fp_Texture_First;
3866         CGparameter fp_Texture_Second;
3867         CGparameter fp_Texture_GammaRamps;
3868         CGparameter fp_Texture_Normal;
3869         CGparameter fp_Texture_Color;
3870         CGparameter fp_Texture_Gloss;
3871         CGparameter fp_Texture_Glow;
3872         CGparameter fp_Texture_SecondaryNormal;
3873         CGparameter fp_Texture_SecondaryColor;
3874         CGparameter fp_Texture_SecondaryGloss;
3875         CGparameter fp_Texture_SecondaryGlow;
3876         CGparameter fp_Texture_Pants;
3877         CGparameter fp_Texture_Shirt;
3878         CGparameter fp_Texture_FogHeightTexture;
3879         CGparameter fp_Texture_FogMask;
3880         CGparameter fp_Texture_Lightmap;
3881         CGparameter fp_Texture_Deluxemap;
3882         CGparameter fp_Texture_Attenuation;
3883         CGparameter fp_Texture_Cube;
3884         CGparameter fp_Texture_Refraction;
3885         CGparameter fp_Texture_Reflection;
3886         CGparameter fp_Texture_ShadowMap2D;
3887         CGparameter fp_Texture_CubeProjection;
3888         CGparameter fp_Texture_ScreenDepth;
3889         CGparameter fp_Texture_ScreenNormalMap;
3890         CGparameter fp_Texture_ScreenDiffuse;
3891         CGparameter fp_Texture_ScreenSpecular;
3892         CGparameter fp_Texture_ReflectMask;
3893         CGparameter fp_Texture_ReflectCube;
3894         CGparameter fp_Alpha;
3895         CGparameter fp_BloomBlur_Parameters;
3896         CGparameter fp_ClientTime;
3897         CGparameter fp_Color_Ambient;
3898         CGparameter fp_Color_Diffuse;
3899         CGparameter fp_Color_Specular;
3900         CGparameter fp_Color_Glow;
3901         CGparameter fp_Color_Pants;
3902         CGparameter fp_Color_Shirt;
3903         CGparameter fp_DeferredColor_Ambient;
3904         CGparameter fp_DeferredColor_Diffuse;
3905         CGparameter fp_DeferredColor_Specular;
3906         CGparameter fp_DeferredMod_Diffuse;
3907         CGparameter fp_DeferredMod_Specular;
3908         CGparameter fp_DistortScaleRefractReflect;
3909         CGparameter fp_EyePosition;
3910         CGparameter fp_FogColor;
3911         CGparameter fp_FogHeightFade;
3912         CGparameter fp_FogPlane;
3913         CGparameter fp_FogPlaneViewDist;
3914         CGparameter fp_FogRangeRecip;
3915         CGparameter fp_LightColor;
3916         CGparameter fp_LightDir;
3917         CGparameter fp_LightPosition;
3918         CGparameter fp_OffsetMapping_Scale;
3919         CGparameter fp_PixelSize;
3920         CGparameter fp_ReflectColor;
3921         CGparameter fp_ReflectFactor;
3922         CGparameter fp_ReflectOffset;
3923         CGparameter fp_RefractColor;
3924         CGparameter fp_Saturation;
3925         CGparameter fp_ScreenCenterRefractReflect;
3926         CGparameter fp_ScreenScaleRefractReflect;
3927         CGparameter fp_ScreenToDepth;
3928         CGparameter fp_ShadowMap_Parameters;
3929         CGparameter fp_ShadowMap_TextureScale;
3930         CGparameter fp_SpecularPower;
3931         CGparameter fp_UserVec1;
3932         CGparameter fp_UserVec2;
3933         CGparameter fp_UserVec3;
3934         CGparameter fp_UserVec4;
3935         CGparameter fp_ViewTintColor;
3936         CGparameter fp_ViewToLight;
3937         CGparameter fp_PixelToScreenTexCoord;
3938         CGparameter fp_ModelToReflectCube;
3939         CGparameter fp_BloomColorSubtract;
3940 }
3941 r_cg_permutation_t;
3942
3943 /// information about each possible shader permutation
3944 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3945 /// currently selected permutation
3946 r_cg_permutation_t *r_cg_permutation;
3947 /// storage for permutations linked in the hash table
3948 memexpandablearray_t r_cg_permutationarray;
3949
3950 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3951
3952 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3953 {
3954         //unsigned int hashdepth = 0;
3955         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3956         r_cg_permutation_t *p;
3957         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3958         {
3959                 if (p->mode == mode && p->permutation == permutation)
3960                 {
3961                         //if (hashdepth > 10)
3962                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3963                         return p;
3964                 }
3965                 //hashdepth++;
3966         }
3967         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3968         p->mode = mode;
3969         p->permutation = permutation;
3970         p->hashnext = r_cg_permutationhash[mode][hashindex];
3971         r_cg_permutationhash[mode][hashindex] = p;
3972         //if (hashdepth > 10)
3973         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3974         return p;
3975 }
3976
3977 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3978 {
3979         char *shaderstring;
3980         if (!filename || !filename[0])
3981                 return NULL;
3982         if (!strcmp(filename, "cg/default.cg"))
3983         {
3984                 if (!cgshaderstring)
3985                 {
3986                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3987                         if (cgshaderstring)
3988                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3989                         else
3990                                 cgshaderstring = (char *)builtincgshaderstring;
3991                 }
3992                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3993                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3994                 return shaderstring;
3995         }
3996         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3997         if (shaderstring)
3998         {
3999                 if (printfromdisknotice)
4000                         Con_DPrintf("from disk %s... ", filename);
4001                 return shaderstring;
4002         }
4003         return shaderstring;
4004 }
4005
4006 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4007 {
4008         // TODO: load or create .fp and .vp shader files
4009 }
4010
4011 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4012 {
4013         int i;
4014         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4015         int vertstrings_count = 0, vertstring_length = 0;
4016         int geomstrings_count = 0, geomstring_length = 0;
4017         int fragstrings_count = 0, fragstring_length = 0;
4018         char *t;
4019         char *vertexstring, *geometrystring, *fragmentstring;
4020         char *vertstring, *geomstring, *fragstring;
4021         const char *vertstrings_list[32+3];
4022         const char *geomstrings_list[32+3];
4023         const char *fragstrings_list[32+3];
4024         char permutationname[256];
4025         char cachename[256];
4026         CGprofile vertexProfile;
4027         CGprofile fragmentProfile;
4028
4029         if (p->compiled)
4030                 return;
4031         p->compiled = true;
4032         p->vprogram = NULL;
4033         p->fprogram = NULL;
4034
4035         permutationname[0] = 0;
4036         cachename[0] = 0;
4037         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4038         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4039         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4040
4041         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4042         strlcat(cachename, "cg/", sizeof(cachename));
4043
4044         // the first pretext is which type of shader to compile as
4045         // (later these will all be bound together as a program object)
4046         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4047         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4048         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4049
4050         // the second pretext is the mode (for example a light source)
4051         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4052         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4053         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4054         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4055         strlcat(cachename, modeinfo->name, sizeof(cachename));
4056
4057         // now add all the permutation pretexts
4058         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4059         {
4060                 if (permutation & (1<<i))
4061                 {
4062                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4063                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4064                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4065                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4066                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4067                 }
4068                 else
4069                 {
4070                         // keep line numbers correct
4071                         vertstrings_list[vertstrings_count++] = "\n";
4072                         geomstrings_list[geomstrings_count++] = "\n";
4073                         fragstrings_list[fragstrings_count++] = "\n";
4074                 }
4075         }
4076
4077         // replace spaces in the cachename with _ characters
4078         for (i = 0;cachename[i];i++)
4079                 if (cachename[i] == ' ')
4080                         cachename[i] = '_';
4081
4082         // now append the shader text itself
4083         vertstrings_list[vertstrings_count++] = vertexstring;
4084         geomstrings_list[geomstrings_count++] = geometrystring;
4085         fragstrings_list[fragstrings_count++] = fragmentstring;
4086
4087         // if any sources were NULL, clear the respective list
4088         if (!vertexstring)
4089                 vertstrings_count = 0;
4090         if (!geometrystring)
4091                 geomstrings_count = 0;
4092         if (!fragmentstring)
4093                 fragstrings_count = 0;
4094
4095         vertstring_length = 0;
4096         for (i = 0;i < vertstrings_count;i++)
4097                 vertstring_length += strlen(vertstrings_list[i]);
4098         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4099         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4100                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4101
4102         geomstring_length = 0;
4103         for (i = 0;i < geomstrings_count;i++)
4104                 geomstring_length += strlen(geomstrings_list[i]);
4105         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4106         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4107                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4108
4109         fragstring_length = 0;
4110         for (i = 0;i < fragstrings_count;i++)
4111                 fragstring_length += strlen(fragstrings_list[i]);
4112         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4113         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4114                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4115
4116         CHECKGLERROR
4117         CHECKCGERROR
4118         //vertexProfile = CG_PROFILE_ARBVP1;
4119         //fragmentProfile = CG_PROFILE_ARBFP1;
4120         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4121         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4122         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4123         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4124         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4125         CHECKGLERROR
4126
4127         // try to load the cached shader, or generate one
4128         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4129
4130         // if caching failed, do a dynamic compile for now
4131         CHECKCGERROR
4132         if (vertstring[0] && !p->vprogram)
4133                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4134         CHECKCGERROR
4135         if (fragstring[0] && !p->fprogram)
4136                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4137         CHECKCGERROR
4138
4139         // look up all the uniform variable names we care about, so we don't
4140         // have to look them up every time we set them
4141         if (p->vprogram)
4142         {
4143                 CHECKCGERROR
4144                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4145                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4146                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4147                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4148                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4149                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4150                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4151                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4152                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4153                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4154                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4155                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4156                 CHECKCGERROR
4157         }
4158         if (p->fprogram)
4159         {
4160                 CHECKCGERROR
4161                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4162                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4163                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4164                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4165                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4166                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4167                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4168                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4169                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4170                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4171                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4172                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4173                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4174                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4175                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4176                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4177                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4178                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4179                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4180                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4181                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4182                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4183                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4184                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4185                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4186                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4187                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4188                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4189                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4190                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4191                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4192                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4193                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4194                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4195                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4196                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4197                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4198                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4199                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4200                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4201                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4202                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4203                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4204                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4205                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4206                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4207                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4208                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4209                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4210                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4211                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4212                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4213                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4214                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4215                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4216                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4217                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4218                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4219                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4220                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4221                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4222                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4223                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4224                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4225                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4226                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4227                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4228                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4229                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4230                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4231                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4232                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4233                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4234                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4235                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4236                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4237                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4238                 CHECKCGERROR
4239         }
4240
4241         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4242                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4243         else
4244                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4245
4246         // free the strings
4247         if (vertstring)
4248                 Mem_Free(vertstring);
4249         if (geomstring)
4250                 Mem_Free(geomstring);
4251         if (fragstring)
4252                 Mem_Free(fragstring);
4253         if (vertexstring)
4254                 Mem_Free(vertexstring);
4255         if (geometrystring)
4256                 Mem_Free(geometrystring);
4257         if (fragmentstring)
4258                 Mem_Free(fragmentstring);
4259 }
4260
4261 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4262 {
4263         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4264         CHECKGLERROR
4265         CHECKCGERROR
4266         if (r_cg_permutation != perm)
4267         {
4268                 r_cg_permutation = perm;
4269                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4270                 {
4271                         if (!r_cg_permutation->compiled)
4272                                 R_CG_CompilePermutation(perm, mode, permutation);
4273                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4274                         {
4275                                 // remove features until we find a valid permutation
4276                                 int i;
4277                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4278                                 {
4279                                         // reduce i more quickly whenever it would not remove any bits
4280                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4281                                         if (!(permutation & j))
4282                                                 continue;
4283                                         permutation -= j;
4284                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4285                                         if (!r_cg_permutation->compiled)
4286                                                 R_CG_CompilePermutation(perm, mode, permutation);
4287                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4288                                                 break;
4289                                 }
4290                                 if (i >= SHADERPERMUTATION_COUNT)
4291                                 {
4292                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4293                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4294                                         return; // no bit left to clear, entire mode is broken
4295                                 }
4296                         }
4297                 }
4298                 CHECKGLERROR
4299                 CHECKCGERROR
4300                 if (r_cg_permutation->vprogram)
4301                 {
4302                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4303                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4304                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4305                 }
4306                 else
4307                 {
4308                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4309                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4310                 }
4311                 if (r_cg_permutation->fprogram)
4312                 {
4313                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4314                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4315                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4316                 }
4317                 else
4318                 {
4319                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4320                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4321                 }
4322         }
4323         CHECKCGERROR
4324         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4325         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4326         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4327 }
4328
4329 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4330 {
4331         cgGLSetTextureParameter(param, R_GetTexture(tex));
4332         cgGLEnableTextureParameter(param);
4333 }
4334 #endif
4335
4336 #ifdef SUPPORTD3D
4337
4338 #ifdef SUPPORTD3D
4339 #include <d3d9.h>
4340 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4341 extern D3DCAPS9 vid_d3d9caps;
4342 #endif
4343
4344 struct r_hlsl_permutation_s;
4345 typedef struct r_hlsl_permutation_s
4346 {
4347         /// hash lookup data
4348         struct r_hlsl_permutation_s *hashnext;
4349         unsigned int mode;
4350         unsigned int permutation;
4351
4352         /// indicates if we have tried compiling this permutation already
4353         qboolean compiled;
4354         /// NULL if compilation failed
4355         IDirect3DVertexShader9 *vertexshader;
4356         IDirect3DPixelShader9 *pixelshader;
4357 }
4358 r_hlsl_permutation_t;
4359
4360 typedef enum D3DVSREGISTER_e
4361 {
4362         D3DVSREGISTER_TexMatrix = 0, // float4x4
4363         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4364         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4365         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4366         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4367         D3DVSREGISTER_ModelToLight = 20, // float4x4
4368         D3DVSREGISTER_EyePosition = 24,
4369         D3DVSREGISTER_FogPlane = 25,
4370         D3DVSREGISTER_LightDir = 26,
4371         D3DVSREGISTER_LightPosition = 27,
4372 }
4373 D3DVSREGISTER_t;
4374
4375 typedef enum D3DPSREGISTER_e
4376 {
4377         D3DPSREGISTER_Alpha = 0,
4378         D3DPSREGISTER_BloomBlur_Parameters = 1,
4379         D3DPSREGISTER_ClientTime = 2,
4380         D3DPSREGISTER_Color_Ambient = 3,
4381         D3DPSREGISTER_Color_Diffuse = 4,
4382         D3DPSREGISTER_Color_Specular = 5,
4383         D3DPSREGISTER_Color_Glow = 6,
4384         D3DPSREGISTER_Color_Pants = 7,
4385         D3DPSREGISTER_Color_Shirt = 8,
4386         D3DPSREGISTER_DeferredColor_Ambient = 9,
4387         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4388         D3DPSREGISTER_DeferredColor_Specular = 11,
4389         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4390         D3DPSREGISTER_DeferredMod_Specular = 13,
4391         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4392         D3DPSREGISTER_EyePosition = 15, // unused
4393         D3DPSREGISTER_FogColor = 16,
4394         D3DPSREGISTER_FogHeightFade = 17,
4395         D3DPSREGISTER_FogPlane = 18,
4396         D3DPSREGISTER_FogPlaneViewDist = 19,
4397         D3DPSREGISTER_FogRangeRecip = 20,
4398         D3DPSREGISTER_LightColor = 21,
4399         D3DPSREGISTER_LightDir = 22, // unused
4400         D3DPSREGISTER_LightPosition = 23,
4401         D3DPSREGISTER_OffsetMapping_Scale = 24,
4402         D3DPSREGISTER_PixelSize = 25,
4403         D3DPSREGISTER_ReflectColor = 26,
4404         D3DPSREGISTER_ReflectFactor = 27,
4405         D3DPSREGISTER_ReflectOffset = 28,
4406         D3DPSREGISTER_RefractColor = 29,
4407         D3DPSREGISTER_Saturation = 30,
4408         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4409         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4410         D3DPSREGISTER_ScreenToDepth = 33,
4411         D3DPSREGISTER_ShadowMap_Parameters = 34,
4412         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4413         D3DPSREGISTER_SpecularPower = 36,
4414         D3DPSREGISTER_UserVec1 = 37,
4415         D3DPSREGISTER_UserVec2 = 38,
4416         D3DPSREGISTER_UserVec3 = 39,
4417         D3DPSREGISTER_UserVec4 = 40,
4418         D3DPSREGISTER_ViewTintColor = 41,
4419         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4420         D3DPSREGISTER_BloomColorSubtract = 43,
4421         D3DPSREGISTER_ViewToLight = 44, // float4x4
4422         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4423         // next at 52
4424 }
4425 D3DPSREGISTER_t;
4426
4427 /// information about each possible shader permutation
4428 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4429 /// currently selected permutation
4430 r_hlsl_permutation_t *r_hlsl_permutation;
4431 /// storage for permutations linked in the hash table
4432 memexpandablearray_t r_hlsl_permutationarray;
4433
4434 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4435 {
4436         //unsigned int hashdepth = 0;
4437         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4438         r_hlsl_permutation_t *p;
4439         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4440         {
4441                 if (p->mode == mode && p->permutation == permutation)
4442                 {
4443                         //if (hashdepth > 10)
4444                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4445                         return p;
4446                 }
4447                 //hashdepth++;
4448         }
4449         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4450         p->mode = mode;
4451         p->permutation = permutation;
4452         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4453         r_hlsl_permutationhash[mode][hashindex] = p;
4454         //if (hashdepth > 10)
4455         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4456         return p;
4457 }
4458
4459 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4460 {
4461         char *shaderstring;
4462         if (!filename || !filename[0])
4463                 return NULL;
4464         if (!strcmp(filename, "hlsl/default.hlsl"))
4465         {
4466                 if (!hlslshaderstring)
4467                 {
4468                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4469                         if (hlslshaderstring)
4470                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4471                         else
4472                                 hlslshaderstring = (char *)builtincgshaderstring;
4473                 }
4474                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4475                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4476                 return shaderstring;
4477         }
4478         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4479         if (shaderstring)
4480         {
4481                 if (printfromdisknotice)
4482                         Con_DPrintf("from disk %s... ", filename);
4483                 return shaderstring;
4484         }
4485         return shaderstring;
4486 }
4487
4488 #include <d3dx9.h>
4489 //#include <d3dx9shader.h>
4490 //#include <d3dx9mesh.h>
4491
4492 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4493 {
4494         DWORD *vsbin = NULL;
4495         DWORD *psbin = NULL;
4496         fs_offset_t vsbinsize;
4497         fs_offset_t psbinsize;
4498 //      IDirect3DVertexShader9 *vs = NULL;
4499 //      IDirect3DPixelShader9 *ps = NULL;
4500         ID3DXBuffer *vslog = NULL;
4501         ID3DXBuffer *vsbuffer = NULL;
4502         ID3DXConstantTable *vsconstanttable = NULL;
4503         ID3DXBuffer *pslog = NULL;
4504         ID3DXBuffer *psbuffer = NULL;
4505         ID3DXConstantTable *psconstanttable = NULL;
4506         int vsresult = 0;
4507         int psresult = 0;
4508         char temp[MAX_INPUTLINE];
4509         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4510         qboolean debugshader = gl_paranoid.integer != 0;
4511         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4512         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4513         if (!debugshader)
4514         {
4515                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4516                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4517         }
4518         if ((!vsbin && vertstring) || (!psbin && fragstring))
4519         {
4520                 const char* dllnames_d3dx9 [] =
4521                 {
4522                         "d3dx9_43.dll",
4523                         "d3dx9_42.dll",
4524                         "d3dx9_41.dll",
4525                         "d3dx9_40.dll",
4526                         "d3dx9_39.dll",
4527                         "d3dx9_38.dll",
4528                         "d3dx9_37.dll",
4529                         "d3dx9_36.dll",
4530                         "d3dx9_35.dll",
4531                         "d3dx9_34.dll",
4532                         "d3dx9_33.dll",
4533                         "d3dx9_32.dll",
4534                         "d3dx9_31.dll",
4535                         "d3dx9_30.dll",
4536                         "d3dx9_29.dll",
4537                         "d3dx9_28.dll",
4538                         "d3dx9_27.dll",
4539                         "d3dx9_26.dll",
4540                         "d3dx9_25.dll",
4541                         "d3dx9_24.dll",
4542                         NULL
4543                 };
4544                 dllhandle_t d3dx9_dll = NULL;
4545                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4546                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4547                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4548                 dllfunction_t d3dx9_dllfuncs[] =
4549                 {
4550                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4551                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4552                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4553                         {NULL, NULL}
4554                 };
4555                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4556                 {
4557                         DWORD shaderflags = 0;
4558                         if (debugshader)
4559                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4560                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4561                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4562                         if (vertstring && vertstring[0])
4563                         {
4564                                 if (debugshader)
4565                                 {
4566 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4567 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4568                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4569                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4570                                 }
4571                                 else
4572                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4573                                 if (vsbuffer)
4574                                 {
4575                                         vsbinsize = vsbuffer->GetBufferSize();
4576                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4577                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4578                                         vsbuffer->Release();
4579                                 }
4580                                 if (vslog)
4581                                 {
4582                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4583                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4584                                         vslog->Release();
4585                                 }
4586                         }
4587                         if (fragstring && fragstring[0])
4588                         {
4589                                 if (debugshader)
4590                                 {
4591 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4592 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4593                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4594                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4595                                 }
4596                                 else
4597                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4598                                 if (psbuffer)
4599                                 {
4600                                         psbinsize = psbuffer->GetBufferSize();
4601                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4602                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4603                                         psbuffer->Release();
4604                                 }
4605                                 if (pslog)
4606                                 {
4607                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4608                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4609                                         pslog->Release();
4610                                 }
4611                         }
4612                         Sys_UnloadLibrary(&d3dx9_dll);
4613                 }
4614                 else
4615                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4616         }
4617         if (vsbin && psbin)
4618         {
4619                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4620                 if (FAILED(vsresult))
4621                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4622                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4623                 if (FAILED(psresult))
4624                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4625         }
4626         // free the shader data
4627         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4628         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4629 }
4630
4631 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4632 {
4633         int i;
4634         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4635         int vertstrings_count = 0, vertstring_length = 0;
4636         int geomstrings_count = 0, geomstring_length = 0;
4637         int fragstrings_count = 0, fragstring_length = 0;
4638         char *t;
4639         char *vertexstring, *geometrystring, *fragmentstring;
4640         char *vertstring, *geomstring, *fragstring;
4641         const char *vertstrings_list[32+3];
4642         const char *geomstrings_list[32+3];
4643         const char *fragstrings_list[32+3];
4644         char permutationname[256];
4645         char cachename[256];
4646
4647         if (p->compiled)
4648                 return;
4649         p->compiled = true;
4650         p->vertexshader = NULL;
4651         p->pixelshader = NULL;
4652
4653         permutationname[0] = 0;
4654         cachename[0] = 0;
4655         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4656         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4657         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4658
4659         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4660         strlcat(cachename, "hlsl/", sizeof(cachename));
4661
4662         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4663         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4664         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4665         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4666
4667         // the first pretext is which type of shader to compile as
4668         // (later these will all be bound together as a program object)
4669         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4670         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4671         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4672
4673         // the second pretext is the mode (for example a light source)
4674         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4675         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4676         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4677         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4678         strlcat(cachename, modeinfo->name, sizeof(cachename));
4679
4680         // now add all the permutation pretexts
4681         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4682         {
4683                 if (permutation & (1<<i))
4684                 {
4685                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4686                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4687                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4688                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4689                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4690                 }
4691                 else
4692                 {
4693                         // keep line numbers correct
4694                         vertstrings_list[vertstrings_count++] = "\n";
4695                         geomstrings_list[geomstrings_count++] = "\n";
4696                         fragstrings_list[fragstrings_count++] = "\n";
4697                 }
4698         }
4699
4700         // replace spaces in the cachename with _ characters
4701         for (i = 0;cachename[i];i++)
4702                 if (cachename[i] == ' ')
4703                         cachename[i] = '_';
4704
4705         // now append the shader text itself
4706         vertstrings_list[vertstrings_count++] = vertexstring;
4707         geomstrings_list[geomstrings_count++] = geometrystring;
4708         fragstrings_list[fragstrings_count++] = fragmentstring;
4709
4710         // if any sources were NULL, clear the respective list
4711         if (!vertexstring)
4712                 vertstrings_count = 0;
4713         if (!geometrystring)
4714                 geomstrings_count = 0;
4715         if (!fragmentstring)
4716                 fragstrings_count = 0;
4717
4718         vertstring_length = 0;
4719         for (i = 0;i < vertstrings_count;i++)
4720                 vertstring_length += strlen(vertstrings_list[i]);
4721         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4722         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4723                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4724
4725         geomstring_length = 0;
4726         for (i = 0;i < geomstrings_count;i++)
4727                 geomstring_length += strlen(geomstrings_list[i]);
4728         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4729         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4730                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4731
4732         fragstring_length = 0;
4733         for (i = 0;i < fragstrings_count;i++)
4734                 fragstring_length += strlen(fragstrings_list[i]);
4735         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4736         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4737                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4738
4739         // try to load the cached shader, or generate one
4740         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4741
4742         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4743                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4744         else
4745                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4746
4747         // free the strings
4748         if (vertstring)
4749                 Mem_Free(vertstring);
4750         if (geomstring)
4751                 Mem_Free(geomstring);
4752         if (fragstring)
4753                 Mem_Free(fragstring);
4754         if (vertexstring)
4755                 Mem_Free(vertexstring);
4756         if (geometrystring)
4757                 Mem_Free(geometrystring);
4758         if (fragmentstring)
4759                 Mem_Free(fragmentstring);
4760 }
4761
4762 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4763 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4764 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4765 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4766 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4767 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4768
4769 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4770 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4771 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4772 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4773 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4774 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4775
4776 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4777 {
4778         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4779         if (r_hlsl_permutation != perm)
4780         {
4781                 r_hlsl_permutation = perm;
4782                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4783                 {
4784                         if (!r_hlsl_permutation->compiled)
4785                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4786                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4787                         {
4788                                 // remove features until we find a valid permutation
4789                                 int i;
4790                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4791                                 {
4792                                         // reduce i more quickly whenever it would not remove any bits
4793                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4794                                         if (!(permutation & j))
4795                                                 continue;
4796                                         permutation -= j;
4797                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4798                                         if (!r_hlsl_permutation->compiled)
4799                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4800                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4801                                                 break;
4802                                 }
4803                                 if (i >= SHADERPERMUTATION_COUNT)
4804                                 {
4805                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4806                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4807                                         return; // no bit left to clear, entire mode is broken
4808                                 }
4809                         }
4810                 }
4811                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4812                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4813         }
4814         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4815         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4816         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4817 }
4818 #endif
4819
4820 void R_GLSL_Restart_f(void)
4821 {
4822         unsigned int i, limit;
4823         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4824                 Mem_Free(glslshaderstring);
4825         glslshaderstring = NULL;
4826         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4827                 Mem_Free(cgshaderstring);
4828         cgshaderstring = NULL;
4829         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4830                 Mem_Free(hlslshaderstring);
4831         hlslshaderstring = NULL;
4832         switch(vid.renderpath)
4833         {
4834         case RENDERPATH_D3D9:
4835 #ifdef SUPPORTD3D
4836                 {
4837                         r_hlsl_permutation_t *p;
4838                         r_hlsl_permutation = NULL;
4839 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4840 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4841 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4842 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4843                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4844                         for (i = 0;i < limit;i++)
4845                         {
4846                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4847                                 {
4848                                         if (p->vertexshader)
4849                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4850                                         if (p->pixelshader)
4851                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4852                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4853                                 }
4854                         }
4855                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4856                 }
4857 #endif
4858                 break;
4859         case RENDERPATH_D3D10:
4860                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4861                 break;
4862         case RENDERPATH_D3D11:
4863                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4864                 break;
4865         case RENDERPATH_GL20:
4866                 {
4867                         r_glsl_permutation_t *p;
4868                         r_glsl_permutation = NULL;
4869                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4870                         for (i = 0;i < limit;i++)
4871                         {
4872                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4873                                 {
4874                                         GL_Backend_FreeProgram(p->program);
4875                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4876                                 }
4877                         }
4878                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4879                 }
4880                 break;
4881         case RENDERPATH_CGGL:
4882 #ifdef SUPPORTCG
4883                 {
4884                         r_cg_permutation_t *p;
4885                         r_cg_permutation = NULL;
4886                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4887                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4888                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4889                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4890                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4891                         for (i = 0;i < limit;i++)
4892                         {
4893                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4894                                 {
4895                                         if (p->vprogram)
4896                                                 cgDestroyProgram(p->vprogram);
4897                                         if (p->fprogram)
4898                                                 cgDestroyProgram(p->fprogram);
4899                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4900                                 }
4901                         }
4902                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4903                 }
4904 #endif
4905                 break;
4906         case RENDERPATH_GL13:
4907         case RENDERPATH_GL11:
4908                 break;
4909         }
4910 }
4911
4912 void R_GLSL_DumpShader_f(void)
4913 {
4914         int i;
4915         qfile_t *file;
4916
4917         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4918         if (file)
4919         {
4920                 FS_Print(file, "/* The engine may define the following macros:\n");
4921                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4922                 for (i = 0;i < SHADERMODE_COUNT;i++)
4923                         FS_Print(file, glslshadermodeinfo[i].pretext);
4924                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4925                         FS_Print(file, shaderpermutationinfo[i].pretext);
4926                 FS_Print(file, "*/\n");
4927                 FS_Print(file, builtinshaderstring);
4928                 FS_Close(file);
4929                 Con_Printf("glsl/default.glsl written\n");
4930         }
4931         else
4932                 Con_Printf("failed to write to glsl/default.glsl\n");
4933
4934 #ifdef SUPPORTCG
4935         file = FS_OpenRealFile("cg/default.cg", "w", false);
4936         if (file)
4937         {
4938                 FS_Print(file, "/* The engine may define the following macros:\n");
4939                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4940                 for (i = 0;i < SHADERMODE_COUNT;i++)
4941                         FS_Print(file, cgshadermodeinfo[i].pretext);
4942                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4943                         FS_Print(file, shaderpermutationinfo[i].pretext);
4944                 FS_Print(file, "*/\n");
4945                 FS_Print(file, builtincgshaderstring);
4946                 FS_Close(file);
4947                 Con_Printf("cg/default.cg written\n");
4948         }
4949         else
4950                 Con_Printf("failed to write to cg/default.cg\n");
4951 #endif
4952
4953 #ifdef SUPPORTD3D
4954         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4955         if (file)
4956         {
4957                 FS_Print(file, "/* The engine may define the following macros:\n");
4958                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4959                 for (i = 0;i < SHADERMODE_COUNT;i++)
4960                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4961                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4962                         FS_Print(file, shaderpermutationinfo[i].pretext);
4963                 FS_Print(file, "*/\n");
4964                 FS_Print(file, builtincgshaderstring);
4965                 FS_Close(file);
4966                 Con_Printf("hlsl/default.hlsl written\n");
4967         }
4968         else
4969                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4970 #endif
4971 }
4972
4973 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4974 {
4975         if (!second)
4976                 texturemode = GL_MODULATE;
4977         switch (vid.renderpath)
4978         {
4979         case RENDERPATH_D3D9:
4980 #ifdef SUPPORTD3D
4981                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4982                 R_Mesh_TexBind(GL20TU_FIRST , first );
4983                 R_Mesh_TexBind(GL20TU_SECOND, second);
4984 #endif
4985                 break;
4986         case RENDERPATH_D3D10:
4987                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4988                 break;
4989         case RENDERPATH_D3D11:
4990                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4991                 break;
4992         case RENDERPATH_GL20:
4993                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4994                 R_Mesh_TexBind(GL20TU_FIRST , first );
4995                 R_Mesh_TexBind(GL20TU_SECOND, second);
4996                 break;
4997         case RENDERPATH_CGGL:
4998 #ifdef SUPPORTCG
4999                 CHECKCGERROR
5000                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5001                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5002                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5003 #endif
5004                 break;
5005         case RENDERPATH_GL13:
5006                 R_Mesh_TexBind(0, first );
5007                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5008                 R_Mesh_TexBind(1, second);
5009                 if (second)
5010                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5011                 break;
5012         case RENDERPATH_GL11:
5013                 R_Mesh_TexBind(0, first );
5014                 break;
5015         }
5016 }
5017
5018 void R_SetupShader_DepthOrShadow(void)
5019 {
5020         switch (vid.renderpath)
5021         {
5022         case RENDERPATH_D3D9:
5023 #ifdef SUPPORTD3D
5024                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5025 #endif
5026                 break;
5027         case RENDERPATH_D3D10:
5028                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5029                 break;
5030         case RENDERPATH_D3D11:
5031                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5032                 break;
5033         case RENDERPATH_GL20:
5034                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5035                 break;
5036         case RENDERPATH_CGGL:
5037 #ifdef SUPPORTCG
5038                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5039 #endif
5040                 break;
5041         case RENDERPATH_GL13:
5042                 R_Mesh_TexBind(0, 0);
5043                 R_Mesh_TexBind(1, 0);
5044                 break;
5045         case RENDERPATH_GL11:
5046                 R_Mesh_TexBind(0, 0);
5047                 break;
5048         }
5049 }
5050
5051 void R_SetupShader_ShowDepth(void)
5052 {
5053         switch (vid.renderpath)
5054         {
5055         case RENDERPATH_D3D9:
5056 #ifdef SUPPORTHLSL
5057                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5058 #endif
5059                 break;
5060         case RENDERPATH_D3D10:
5061                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5062                 break;
5063         case RENDERPATH_D3D11:
5064                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5065                 break;
5066         case RENDERPATH_GL20:
5067                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5068                 break;
5069         case RENDERPATH_CGGL:
5070 #ifdef SUPPORTCG
5071                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5072 #endif
5073                 break;
5074         case RENDERPATH_GL13:
5075                 break;
5076         case RENDERPATH_GL11:
5077                 break;
5078         }
5079 }
5080
5081 extern qboolean r_shadow_usingdeferredprepass;
5082 extern cvar_t r_shadow_deferred_8bitrange;
5083 extern rtexture_t *r_shadow_attenuationgradienttexture;
5084 extern rtexture_t *r_shadow_attenuation2dtexture;
5085 extern rtexture_t *r_shadow_attenuation3dtexture;
5086 extern qboolean r_shadow_usingshadowmap2d;
5087 extern qboolean r_shadow_usingshadowmaportho;
5088 extern float r_shadow_shadowmap_texturescale[2];
5089 extern float r_shadow_shadowmap_parameters[4];
5090 extern qboolean r_shadow_shadowmapvsdct;
5091 extern qboolean r_shadow_shadowmapsampler;
5092 extern int r_shadow_shadowmappcf;
5093 extern rtexture_t *r_shadow_shadowmap2dtexture;
5094 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5095 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5096 extern matrix4x4_t r_shadow_shadowmapmatrix;
5097 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5098 extern int r_shadow_prepass_width;
5099 extern int r_shadow_prepass_height;
5100 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5101 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5102 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5103 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5104 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5105 extern cvar_t gl_mesh_separatearrays;
5106 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5107 {
5108         // a blendfunc allows colormod if:
5109         // a) it can never keep the destination pixel invariant, or
5110         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5111         // this is to prevent unintended side effects from colormod
5112
5113         // in formulas:
5114         // IF there is a (s, sa) for which for all (d, da),
5115         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5116         // THEN, for this (s, sa) and all (colormod, d, da):
5117         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5118         // OBVIOUSLY, this means that
5119         //   s*colormod * src(s*colormod, d, sa, da) = 0
5120         //   dst(s*colormod, d, sa, da)              = 1
5121
5122         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5123
5124         // main condition to leave dst color invariant:
5125         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5126         //   src == GL_ZERO:
5127         //     s * 0 + d * dst(s, d, sa, da) == d
5128         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5129         //       => colormod is a problem for GL_SRC_COLOR only
5130         //   src == GL_ONE:
5131         //     s + d * dst(s, d, sa, da) == d
5132         //       => s == 0
5133         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5134         //       => colormod is never problematic for these
5135         //   src == GL_SRC_COLOR:
5136         //     s*s + d * dst(s, d, sa, da) == d
5137         //       => s == 0
5138         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5139         //       => colormod is never problematic for these
5140         //   src == GL_ONE_MINUS_SRC_COLOR:
5141         //     s*(1-s) + d * dst(s, d, sa, da) == d
5142         //       => s == 0 or s == 1
5143         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5144         //       => colormod is a problem for GL_SRC_COLOR only
5145         //   src == GL_DST_COLOR
5146         //     s*d + d * dst(s, d, sa, da) == d
5147         //       => s == 1
5148         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5149         //       => colormod is always a problem
5150         //     or
5151         //       => s == 0
5152         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5153         //       => colormod is never problematic for these
5154         //       => BUT, we do not know s! We must assume it is problematic
5155         //       then... except in GL_ONE case, where we know all invariant
5156         //       cases are fine
5157         //   src == GL_ONE_MINUS_DST_COLOR
5158         //     s*(1-d) + d * dst(s, d, sa, da) == d
5159         //       => s == 0 (1-d is impossible to handle for our desired result)
5160         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5161         //       => colormod is never problematic for these
5162         //   src == GL_SRC_ALPHA
5163         //     s*sa + d * dst(s, d, sa, da) == d
5164         //       => s == 0, or sa == 0
5165         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5166         //       => colormod breaks in the case GL_SRC_COLOR only
5167         //   src == GL_ONE_MINUS_SRC_ALPHA
5168         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5169         //       => s == 0, or sa == 1
5170         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5171         //       => colormod breaks in the case GL_SRC_COLOR only
5172         //   src == GL_DST_ALPHA
5173         //     s*da + d * dst(s, d, sa, da) == d
5174         //       => s == 0
5175         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5176         //       => colormod is never problematic for these
5177
5178         switch(src)
5179         {
5180                 case GL_ZERO:
5181                 case GL_ONE_MINUS_SRC_COLOR:
5182                 case GL_SRC_ALPHA:
5183                 case GL_ONE_MINUS_SRC_ALPHA:
5184                         if(dst == GL_SRC_COLOR)
5185                                 return false;
5186                         return true;
5187                 case GL_ONE:
5188                 case GL_SRC_COLOR:
5189                 case GL_ONE_MINUS_DST_COLOR:
5190                 case GL_DST_ALPHA:
5191                 case GL_ONE_MINUS_DST_ALPHA:
5192                         return true;
5193                 case GL_DST_COLOR:
5194                         if(dst == GL_ONE)
5195                                 return true;
5196                         return false;
5197                 default:
5198                         return false;
5199         }
5200 }
5201 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5202 {
5203         // select a permutation of the lighting shader appropriate to this
5204         // combination of texture, entity, light source, and fogging, only use the
5205         // minimum features necessary to avoid wasting rendering time in the
5206         // fragment shader on features that are not being used
5207         unsigned int permutation = 0;
5208         unsigned int mode = 0;
5209         qboolean allow_colormod;
5210         static float dummy_colormod[3] = {1, 1, 1};
5211         float *colormod = rsurface.colormod;
5212         float m16f[16];
5213         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5214         if (rsurfacepass == RSURFPASS_BACKGROUND)
5215         {
5216                 // distorted background
5217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5218                         mode = SHADERMODE_WATER;
5219                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5220                         mode = SHADERMODE_REFRACTION;
5221                 else
5222                 {
5223                         mode = SHADERMODE_GENERIC;
5224                         permutation |= SHADERPERMUTATION_DIFFUSE;
5225                 }
5226                 GL_AlphaTest(false);
5227                 GL_BlendFunc(GL_ONE, GL_ZERO);
5228                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5229         }
5230         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5231         {
5232                 if (r_glsl_offsetmapping.integer)
5233                 {
5234                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5235                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5236                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5237                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5238                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5239                         {
5240                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5241                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5242                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5243                         }
5244                 }
5245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5248                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5249                 // normalmap (deferred prepass), may use alpha test on diffuse
5250                 mode = SHADERMODE_DEFERREDGEOMETRY;
5251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5252                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5253                 GL_AlphaTest(false);
5254                 GL_BlendFunc(GL_ONE, GL_ZERO);
5255                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5256         }
5257         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5258         {
5259                 if (r_glsl_offsetmapping.integer)
5260                 {
5261                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5262                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5263                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5264                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5265                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5266                         {
5267                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5268                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5269                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5270                         }
5271                 }
5272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5273                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5274                 // light source
5275                 mode = SHADERMODE_LIGHTSOURCE;
5276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5277                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5278                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5279                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5280                 if (diffusescale > 0)
5281                         permutation |= SHADERPERMUTATION_DIFFUSE;
5282                 if (specularscale > 0)
5283                 {
5284                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5285                         if (r_shadow_glossexact.integer)
5286                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5287                 }
5288                 if (r_refdef.fogenabled)
5289                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5290                 if (rsurface.texture->colormapping)
5291                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5292                 if (r_shadow_usingshadowmap2d)
5293                 {
5294                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5295                         if(r_shadow_shadowmapvsdct)
5296                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5297
5298                         if (r_shadow_shadowmapsampler)
5299                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5300                         if (r_shadow_shadowmappcf > 1)
5301                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5302                         else if (r_shadow_shadowmappcf)
5303                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5304                 }
5305                 if (rsurface.texture->reflectmasktexture)
5306                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5307                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5308                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5309                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5310         }
5311         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5312         {
5313                 if (r_glsl_offsetmapping.integer)
5314                 {
5315                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5316                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5317                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5318                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5319                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5320                         {
5321                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5322                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5323                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5324                         }
5325                 }
5326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5328                 // unshaded geometry (fullbright or ambient model lighting)
5329                 mode = SHADERMODE_FLATCOLOR;
5330                 ambientscale = diffusescale = specularscale = 0;
5331                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5332                         permutation |= SHADERPERMUTATION_GLOW;
5333                 if (r_refdef.fogenabled)
5334                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5335                 if (rsurface.texture->colormapping)
5336                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5337                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5338                 {
5339                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5340                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5341
5342                         if (r_shadow_shadowmapsampler)
5343                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5344                         if (r_shadow_shadowmappcf > 1)
5345                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5346                         else if (r_shadow_shadowmappcf)
5347                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5348                 }
5349                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5350                         permutation |= SHADERPERMUTATION_REFLECTION;
5351                 if (rsurface.texture->reflectmasktexture)
5352                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5353                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5354                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5355                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5356         }
5357         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5358         {
5359                 if (r_glsl_offsetmapping.integer)
5360                 {
5361                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5362                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5363                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5364                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5365                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5366                         {
5367                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5368                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5369                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5370                         }
5371                 }
5372                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5373                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5374                 // directional model lighting
5375                 mode = SHADERMODE_LIGHTDIRECTION;
5376                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5377                         permutation |= SHADERPERMUTATION_GLOW;
5378                 permutation |= SHADERPERMUTATION_DIFFUSE;
5379                 if (specularscale > 0)
5380                 {
5381                         permutation |= SHADERPERMUTATION_SPECULAR;
5382                         if (r_shadow_glossexact.integer)
5383                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5384                 }
5385                 if (r_refdef.fogenabled)
5386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5387                 if (rsurface.texture->colormapping)
5388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5389                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5390                 {
5391                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5392                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5393
5394                         if (r_shadow_shadowmapsampler)
5395                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5396                         if (r_shadow_shadowmappcf > 1)
5397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5398                         else if (r_shadow_shadowmappcf)
5399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5400                 }
5401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5402                         permutation |= SHADERPERMUTATION_REFLECTION;
5403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5405                 if (rsurface.texture->reflectmasktexture)
5406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5407                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5408                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5409                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5410         }
5411         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5412         {
5413                 if (r_glsl_offsetmapping.integer)
5414                 {
5415                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5416                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5417                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5419                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5420                         {
5421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5422                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5423                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5424                         }
5425                 }
5426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5428                 // ambient model lighting
5429                 mode = SHADERMODE_LIGHTDIRECTION;
5430                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5431                         permutation |= SHADERPERMUTATION_GLOW;
5432                 if (r_refdef.fogenabled)
5433                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5434                 if (rsurface.texture->colormapping)
5435                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5436                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5437                 {
5438                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5439                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5440
5441                         if (r_shadow_shadowmapsampler)
5442                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5443                         if (r_shadow_shadowmappcf > 1)
5444                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5445                         else if (r_shadow_shadowmappcf)
5446                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5447                 }
5448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5449                         permutation |= SHADERPERMUTATION_REFLECTION;
5450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5452                 if (rsurface.texture->reflectmasktexture)
5453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5454                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5455                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5456                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5457         }
5458         else
5459         {
5460                 if (r_glsl_offsetmapping.integer)
5461                 {
5462                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5467                         {
5468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5470                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5471                         }
5472                 }
5473                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5475                 // lightmapped wall
5476                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5477                         permutation |= SHADERPERMUTATION_GLOW;
5478                 if (r_refdef.fogenabled)
5479                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5480                 if (rsurface.texture->colormapping)
5481                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5482                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5483                 {
5484                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5485                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5486
5487                         if (r_shadow_shadowmapsampler)
5488                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5489                         if (r_shadow_shadowmappcf > 1)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5491                         else if (r_shadow_shadowmappcf)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5493                 }
5494                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5495                         permutation |= SHADERPERMUTATION_REFLECTION;
5496                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5497                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5498                 if (rsurface.texture->reflectmasktexture)
5499                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5500                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5501                 {
5502                         // deluxemapping (light direction texture)
5503                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5504                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5505                         else
5506                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5507                         permutation |= SHADERPERMUTATION_DIFFUSE;
5508                         if (specularscale > 0)
5509                         {
5510                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5511                                 if (r_shadow_glossexact.integer)
5512                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5513                         }
5514                 }
5515                 else if (r_glsl_deluxemapping.integer >= 2)
5516                 {
5517                         // fake deluxemapping (uniform light direction in tangentspace)
5518                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5519                         permutation |= SHADERPERMUTATION_DIFFUSE;
5520                         if (specularscale > 0)
5521                         {
5522                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5523                                 if (r_shadow_glossexact.integer)
5524                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5525                         }
5526                 }
5527                 else if (rsurface.uselightmaptexture)
5528                 {
5529                         // ordinary lightmapping (q1bsp, q3bsp)
5530                         mode = SHADERMODE_LIGHTMAP;
5531                 }
5532                 else
5533                 {
5534                         // ordinary vertex coloring (q3bsp)
5535                         mode = SHADERMODE_VERTEXCOLOR;
5536                 }
5537                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5538                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5539                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5540         }
5541         if(!allow_colormod)
5542                 colormod = dummy_colormod;
5543         switch(vid.renderpath)
5544         {
5545         case RENDERPATH_D3D9:
5546 #ifdef SUPPORTD3D
5547                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5548                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5549                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5550                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5551                 if (mode == SHADERMODE_LIGHTSOURCE)
5552                 {
5553                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5554                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5555                 }
5556                 else
5557                 {
5558                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5559                         {
5560                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5561                         }
5562                 }
5563                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5564                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5565                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5566                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5567                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5568
5569                 if (mode == SHADERMODE_LIGHTSOURCE)
5570                 {
5571                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5572                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5573                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5574                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5575                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5576
5577                         // additive passes are only darkened by fog, not tinted
5578                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5580                 }
5581                 else
5582                 {
5583                         if (mode == SHADERMODE_FLATCOLOR)
5584                         {
5585                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5586                         }
5587                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5588                         {
5589                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5590                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5591                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5592                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5593                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5594                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5595                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5596                         }
5597                         else
5598                         {
5599                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5600                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5601                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5602                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5603                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5604                         }
5605                         // additive passes are only darkened by fog, not tinted
5606                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5607                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5608                         else
5609                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5610                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5611                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5612                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5613                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5614                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5615                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5616                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5617                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5618                 }
5619                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5620                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5621                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5622                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5623                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5624                 if (rsurface.texture->pantstexture)
5625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5626                 else
5627                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5628                 if (rsurface.texture->shirttexture)
5629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5630                 else
5631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5632                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5633                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5634                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5635                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5636                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5637                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5638                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5639
5640                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5641                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5642                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5643                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5648                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5649                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5650                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5651                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5652                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5653                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5654                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5655                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5656                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5657                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5658                 {
5659                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5660                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5661                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5662                 }
5663                 else
5664                 {
5665                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5666                 }
5667 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5668 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5669                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5671                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5672                 {
5673                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5674                         if (rsurface.rtlight)
5675                         {
5676                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5677                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5678                         }
5679                 }
5680 #endif
5681                 break;
5682         case RENDERPATH_D3D10:
5683                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5684                 break;
5685         case RENDERPATH_D3D11:
5686                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5687                 break;
5688         case RENDERPATH_GL20:
5689                 if (gl_mesh_separatearrays.integer)
5690                 {
5691                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5692                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5693                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5694                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5695                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5696                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5697                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5698                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5699                 }
5700                 else
5701                 {
5702                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5703                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5704                 }
5705                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5706                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5707                 if (mode == SHADERMODE_LIGHTSOURCE)
5708                 {
5709                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5710                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5711                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5712                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5713                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5714                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5715         
5716                         // additive passes are only darkened by fog, not tinted
5717                         if (r_glsl_permutation->loc_FogColor >= 0)
5718                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5719                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5720                 }
5721                 else
5722                 {
5723                         if (mode == SHADERMODE_FLATCOLOR)
5724                         {
5725                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5726                         }
5727                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5728                         {
5729                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5730                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5731                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5732                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5733                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5734                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5735                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5736                         }
5737                         else
5738                         {
5739                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5740                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5741                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5742                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5743                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5744                         }
5745                         // additive passes are only darkened by fog, not tinted
5746                         if (r_glsl_permutation->loc_FogColor >= 0)
5747                         {
5748                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5749                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5750                                 else
5751                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5752                         }
5753                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5754                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5755                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5756                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5757                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5758                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5759                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5760                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5761                 }
5762                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5763                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5764                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5765                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5766                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5767
5768                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5769                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5770                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5771                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5772                 {
5773                         if (rsurface.texture->pantstexture)
5774                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5775                         else
5776                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5777                 }
5778                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5779                 {
5780                         if (rsurface.texture->shirttexture)
5781                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5782                         else
5783                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5784                 }
5785                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5786                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5787                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5788                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5789                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5790                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5791                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5792
5793         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5794         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5795         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5796                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5797                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5798                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5799                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5800                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5801                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5802                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5803                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5804                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5805                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5806                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5807                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5808                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5809                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5810                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5811                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5812                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5813                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5814                 {
5815                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5816                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5817                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5818                 }
5819                 else
5820                 {
5821                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5822                 }
5823 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5824 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5825                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5826                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5827                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5828                 {
5829                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5830                         if (rsurface.rtlight)
5831                         {
5832                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5833                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5834                         }
5835                 }
5836                 CHECKGLERROR
5837                 break;
5838         case RENDERPATH_CGGL:
5839 #ifdef SUPPORTCG
5840                 if (gl_mesh_separatearrays.integer)
5841                 {
5842                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5843                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5850                 }
5851                 else
5852                 {
5853                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5854                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5855                 }
5856                 R_SetupShader_SetPermutationCG(mode, permutation);
5857                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5858                 if (mode == SHADERMODE_LIGHTSOURCE)
5859                 {
5860                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5861                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5862                 }
5863                 else
5864                 {
5865                         if (mode == SHADERMODE_LIGHTDIRECTION)
5866                         {
5867                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5868                         }
5869                 }
5870                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5871                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5872                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5873                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5874                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5875                 CHECKGLERROR
5876
5877                 if (mode == SHADERMODE_LIGHTSOURCE)
5878                 {
5879                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5880                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5881                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5882                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5883                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
5884
5885                         // additive passes are only darkened by fog, not tinted
5886                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5887                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5888                 }
5889                 else
5890                 {
5891                         if (mode == SHADERMODE_FLATCOLOR)
5892                         {
5893                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5894                         }
5895                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5896                         {
5897                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
5898                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
5899                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5900                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5901                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5902                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
5903                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
5904                         }
5905                         else
5906                         {
5907                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
5908                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
5909                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
5910                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5911                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5912                         }
5913                         // additive passes are only darkened by fog, not tinted
5914                         if (r_cg_permutation->fp_FogColor)
5915                         {
5916                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5917                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5918                                 else
5919                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5920                                 CHECKCGERROR
5921                         }
5922                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
5923                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
5924                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
5925                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5926                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5927                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5928                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5929                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5930                 }
5931                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
5932                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
5933                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5934                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5935                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5936                 if (r_cg_permutation->fp_Color_Pants)
5937                 {
5938                         if (rsurface.texture->pantstexture)
5939                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5940                         else
5941                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5942                         CHECKCGERROR
5943                 }
5944                 if (r_cg_permutation->fp_Color_Shirt)
5945                 {
5946                         if (rsurface.texture->shirttexture)
5947                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5948                         else
5949                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5950                         CHECKCGERROR
5951                 }
5952                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
5953                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5954                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5955                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5956                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5957                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
5958                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5959
5960         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5961         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5962         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5963                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5964                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5965                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5966                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5967                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5968                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5969                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5970                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5971                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5972                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5973                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5974                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5975                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5976                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5977                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5978                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5979                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5980                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5981                 {
5982                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
5983                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
5984                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
5985                 }
5986                 else
5987                 {
5988                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
5989                 }
5990                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5991                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5992                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5993                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5994                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5995                 {
5996                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5997                         if (rsurface.rtlight)
5998                         {
5999                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6000                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6001                         }
6002                 }
6003
6004                 CHECKGLERROR
6005 #endif
6006                 break;
6007         case RENDERPATH_GL13:
6008         case RENDERPATH_GL11:
6009                 break;
6010         }
6011 }
6012
6013 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6014 {
6015         // select a permutation of the lighting shader appropriate to this
6016         // combination of texture, entity, light source, and fogging, only use the
6017         // minimum features necessary to avoid wasting rendering time in the
6018         // fragment shader on features that are not being used
6019         unsigned int permutation = 0;
6020         unsigned int mode = 0;
6021         const float *lightcolorbase = rtlight->currentcolor;
6022         float ambientscale = rtlight->ambientscale;
6023         float diffusescale = rtlight->diffusescale;
6024         float specularscale = rtlight->specularscale;
6025         // this is the location of the light in view space
6026         vec3_t viewlightorigin;
6027         // this transforms from view space (camera) to light space (cubemap)
6028         matrix4x4_t viewtolight;
6029         matrix4x4_t lighttoview;
6030         float viewtolight16f[16];
6031         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6032         // light source
6033         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6034         if (rtlight->currentcubemap != r_texture_whitecube)
6035                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6036         if (diffusescale > 0)
6037                 permutation |= SHADERPERMUTATION_DIFFUSE;
6038         if (specularscale > 0)
6039         {
6040                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6041                 if (r_shadow_glossexact.integer)
6042                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6043         }
6044         if (r_shadow_usingshadowmap2d)
6045         {
6046                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6047                 if (r_shadow_shadowmapvsdct)
6048                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6049
6050                 if (r_shadow_shadowmapsampler)
6051                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6052                 if (r_shadow_shadowmappcf > 1)
6053                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6054                 else if (r_shadow_shadowmappcf)
6055                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6056         }
6057         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6058         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6059         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6060         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6061         switch(vid.renderpath)
6062         {
6063         case RENDERPATH_D3D9:
6064 #ifdef SUPPORTD3D
6065                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6066                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6067                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6068                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6069                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6070                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6071                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6072                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6073                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6074                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6075                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6076
6077                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6078                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6079                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6080                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6081                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6082                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6083 #endif
6084                 break;
6085         case RENDERPATH_D3D10:
6086                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6087                 break;
6088         case RENDERPATH_D3D11:
6089                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6090                 break;
6091         case RENDERPATH_GL20:
6092                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6093                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6094                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6095                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6096                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6097                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6098                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6099                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6100                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6101                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6102                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6103
6104                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6105                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6106                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6107                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6108                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6109                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6110                 break;
6111         case RENDERPATH_CGGL:
6112 #ifdef SUPPORTCG
6113                 R_SetupShader_SetPermutationCG(mode, permutation);
6114                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6115                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6116                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
6117                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
6118                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6119                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6120                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6121                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6122                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6123                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6124
6125                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6126                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6127                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6128                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6129                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6130                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6131 #endif
6132                 break;
6133         case RENDERPATH_GL13:
6134         case RENDERPATH_GL11:
6135                 break;
6136         }
6137 }
6138
6139 #define SKINFRAME_HASH 1024
6140
6141 typedef struct
6142 {
6143         int loadsequence; // incremented each level change
6144         memexpandablearray_t array;
6145         skinframe_t *hash[SKINFRAME_HASH];
6146 }
6147 r_skinframe_t;
6148 r_skinframe_t r_skinframe;
6149
6150 void R_SkinFrame_PrepareForPurge(void)
6151 {
6152         r_skinframe.loadsequence++;
6153         // wrap it without hitting zero
6154         if (r_skinframe.loadsequence >= 200)
6155                 r_skinframe.loadsequence = 1;
6156 }
6157
6158 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6159 {
6160         if (!skinframe)
6161                 return;
6162         // mark the skinframe as used for the purging code
6163         skinframe->loadsequence = r_skinframe.loadsequence;
6164 }
6165
6166 void R_SkinFrame_Purge(void)
6167 {
6168         int i;
6169         skinframe_t *s;
6170         for (i = 0;i < SKINFRAME_HASH;i++)
6171         {
6172                 for (s = r_skinframe.hash[i];s;s = s->next)
6173                 {
6174                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6175                         {
6176                                 if (s->merged == s->base)
6177                                         s->merged = NULL;
6178                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6179                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6180                                 R_PurgeTexture(s->merged);s->merged = NULL;
6181                                 R_PurgeTexture(s->base  );s->base   = NULL;
6182                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6183                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6184                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6185                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6186                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6187                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6188                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6189                                 s->loadsequence = 0;
6190                         }
6191                 }
6192         }
6193 }
6194
6195 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6196         skinframe_t *item;
6197         char basename[MAX_QPATH];
6198
6199         Image_StripImageExtension(name, basename, sizeof(basename));
6200
6201         if( last == NULL ) {
6202                 int hashindex;
6203                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6204                 item = r_skinframe.hash[hashindex];
6205         } else {
6206                 item = last->next;
6207         }
6208
6209         // linearly search through the hash bucket
6210         for( ; item ; item = item->next ) {
6211                 if( !strcmp( item->basename, basename ) ) {
6212                         return item;
6213                 }
6214         }
6215         return NULL;
6216 }
6217
6218 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6219 {
6220         skinframe_t *item;
6221         int hashindex;
6222         char basename[MAX_QPATH];
6223
6224         Image_StripImageExtension(name, basename, sizeof(basename));
6225
6226         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6227         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6228                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6229                         break;
6230
6231         if (!item) {
6232                 rtexture_t *dyntexture;
6233                 // check whether its a dynamic texture
6234                 dyntexture = CL_GetDynTexture( basename );
6235                 if (!add && !dyntexture)
6236                         return NULL;
6237                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6238                 memset(item, 0, sizeof(*item));
6239                 strlcpy(item->basename, basename, sizeof(item->basename));
6240                 item->base = dyntexture; // either NULL or dyntexture handle
6241                 item->textureflags = textureflags;
6242                 item->comparewidth = comparewidth;
6243                 item->compareheight = compareheight;
6244                 item->comparecrc = comparecrc;
6245                 item->next = r_skinframe.hash[hashindex];
6246                 r_skinframe.hash[hashindex] = item;
6247         }
6248         else if( item->base == NULL )
6249         {
6250                 rtexture_t *dyntexture;
6251                 // check whether its a dynamic texture
6252                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
6253                 dyntexture = CL_GetDynTexture( basename );
6254                 item->base = dyntexture; // either NULL or dyntexture handle
6255         }
6256
6257         R_SkinFrame_MarkUsed(item);
6258         return item;
6259 }
6260
6261 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6262         { \
6263                 unsigned long long avgcolor[5], wsum; \
6264                 int pix, comp, w; \
6265                 avgcolor[0] = 0; \
6266                 avgcolor[1] = 0; \
6267                 avgcolor[2] = 0; \
6268                 avgcolor[3] = 0; \
6269                 avgcolor[4] = 0; \
6270                 wsum = 0; \
6271                 for(pix = 0; pix < cnt; ++pix) \
6272                 { \
6273                         w = 0; \
6274                         for(comp = 0; comp < 3; ++comp) \
6275                                 w += getpixel; \
6276                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6277                         { \
6278                                 ++wsum; \
6279                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6280                                 w = getpixel; \
6281                                 for(comp = 0; comp < 3; ++comp) \
6282                                         avgcolor[comp] += getpixel * w; \
6283                                 avgcolor[3] += w; \
6284                         } \
6285                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6286                         avgcolor[4] += getpixel; \
6287                 } \
6288                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6289                         avgcolor[3] = 1; \
6290                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6291                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6292                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6293                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6294         }
6295
6296 extern cvar_t gl_picmip;
6297 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6298 {
6299         int j;
6300         unsigned char *pixels;
6301         unsigned char *bumppixels;
6302         unsigned char *basepixels = NULL;
6303         int basepixels_width = 0;
6304         int basepixels_height = 0;
6305         skinframe_t *skinframe;
6306         rtexture_t *ddsbase = NULL;
6307         qboolean ddshasalpha = false;
6308         float ddsavgcolor[4];
6309         char basename[MAX_QPATH];
6310         int miplevel = R_PicmipForFlags(textureflags);
6311         int savemiplevel = miplevel;
6312         int mymiplevel;
6313
6314         if (cls.state == ca_dedicated)
6315                 return NULL;
6316
6317         // return an existing skinframe if already loaded
6318         // if loading of the first image fails, don't make a new skinframe as it
6319         // would cause all future lookups of this to be missing
6320         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6321         if (skinframe && skinframe->base)
6322                 return skinframe;
6323
6324         Image_StripImageExtension(name, basename, sizeof(basename));
6325
6326         // check for DDS texture file first
6327         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6328         {
6329                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6330                 if (basepixels == NULL)
6331                         return NULL;
6332         }
6333
6334         // FIXME handle miplevel
6335
6336         if (developer_loading.integer)
6337                 Con_Printf("loading skin \"%s\"\n", name);
6338
6339         // we've got some pixels to store, so really allocate this new texture now
6340         if (!skinframe)
6341                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6342         skinframe->stain = NULL;
6343         skinframe->merged = NULL;
6344         skinframe->base = NULL;
6345         skinframe->pants = NULL;
6346         skinframe->shirt = NULL;
6347         skinframe->nmap = NULL;
6348         skinframe->gloss = NULL;
6349         skinframe->glow = NULL;
6350         skinframe->fog = NULL;
6351         skinframe->reflect = NULL;
6352         skinframe->hasalpha = false;
6353
6354         if (ddsbase)
6355         {
6356                 skinframe->base = ddsbase;
6357                 skinframe->hasalpha = ddshasalpha;
6358                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6359                 if (r_loadfog && skinframe->hasalpha)
6360                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6361                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6362         }
6363         else
6364         {
6365                 basepixels_width = image_width;
6366                 basepixels_height = image_height;
6367                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6368                 if (textureflags & TEXF_ALPHA)
6369                 {
6370                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6371                         {
6372                                 if (basepixels[j] < 255)
6373                                 {
6374                                         skinframe->hasalpha = true;
6375                                         break;
6376                                 }
6377                         }
6378                         if (r_loadfog && skinframe->hasalpha)
6379                         {
6380                                 // has transparent pixels
6381                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6382                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6383                                 {
6384                                         pixels[j+0] = 255;
6385                                         pixels[j+1] = 255;
6386                                         pixels[j+2] = 255;
6387                                         pixels[j+3] = basepixels[j+3];
6388                                 }
6389                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6390                                 Mem_Free(pixels);
6391                         }
6392                 }
6393                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6394                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6395                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6396                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6398                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6399         }
6400
6401         if (r_loaddds)
6402         {
6403                 mymiplevel = savemiplevel;
6404                 if (r_loadnormalmap)
6405                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6406                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6407                 if (r_loadgloss)
6408                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6409                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6410                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6411                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6412         }
6413
6414         // _norm is the name used by tenebrae and has been adopted as standard
6415         if (r_loadnormalmap && skinframe->nmap == NULL)
6416         {
6417                 mymiplevel = savemiplevel;
6418                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6419                 {
6420                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6421                         Mem_Free(pixels);
6422                         pixels = NULL;
6423                 }
6424                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6425                 {
6426                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6427                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6428                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6429                         Mem_Free(pixels);
6430                         Mem_Free(bumppixels);
6431                 }
6432                 else if (r_shadow_bumpscale_basetexture.value > 0)
6433                 {
6434                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6435                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6436                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6437                         Mem_Free(pixels);
6438                 }
6439                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6440                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6441         }
6442
6443         // _luma is supported only for tenebrae compatibility
6444         // _glow is the preferred name
6445         mymiplevel = savemiplevel;
6446         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6447         {
6448                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6449                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6450                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6451                 Mem_Free(pixels);pixels = NULL;
6452         }
6453
6454         mymiplevel = savemiplevel;
6455         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6456         {
6457                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6459                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6460                 Mem_Free(pixels);
6461                 pixels = NULL;
6462         }
6463
6464         mymiplevel = savemiplevel;
6465         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6466         {
6467                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6468                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6469                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6470                 Mem_Free(pixels);
6471                 pixels = NULL;
6472         }
6473
6474         mymiplevel = savemiplevel;
6475         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6476         {
6477                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6479                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6480                 Mem_Free(pixels);
6481                 pixels = NULL;
6482         }
6483
6484         mymiplevel = savemiplevel;
6485         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6486         {
6487                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6489                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6490                 Mem_Free(pixels);
6491                 pixels = NULL;
6492         }
6493
6494         if (basepixels)
6495                 Mem_Free(basepixels);
6496
6497         return skinframe;
6498 }
6499
6500 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6501 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6502 {
6503         int i;
6504         unsigned char *temp1, *temp2;
6505         skinframe_t *skinframe;
6506
6507         if (cls.state == ca_dedicated)
6508                 return NULL;
6509
6510         // if already loaded just return it, otherwise make a new skinframe
6511         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6512         if (skinframe && skinframe->base)
6513                 return skinframe;
6514
6515         skinframe->stain = NULL;
6516         skinframe->merged = NULL;
6517         skinframe->base = NULL;
6518         skinframe->pants = NULL;
6519         skinframe->shirt = NULL;
6520         skinframe->nmap = NULL;
6521         skinframe->gloss = NULL;
6522         skinframe->glow = NULL;
6523         skinframe->fog = NULL;
6524         skinframe->reflect = NULL;
6525         skinframe->hasalpha = false;
6526
6527         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6528         if (!skindata)
6529                 return NULL;
6530
6531         if (developer_loading.integer)
6532                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6533
6534         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6535         {
6536                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6537                 temp2 = temp1 + width * height * 4;
6538                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6539                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6540                 Mem_Free(temp1);
6541         }
6542         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6543         if (textureflags & TEXF_ALPHA)
6544         {
6545                 for (i = 3;i < width * height * 4;i += 4)
6546                 {
6547                         if (skindata[i] < 255)
6548                         {
6549                                 skinframe->hasalpha = true;
6550                                 break;
6551                         }
6552                 }
6553                 if (r_loadfog && skinframe->hasalpha)
6554                 {
6555                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6556                         memcpy(fogpixels, skindata, width * height * 4);
6557                         for (i = 0;i < width * height * 4;i += 4)
6558                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6559                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6560                         Mem_Free(fogpixels);
6561                 }
6562         }
6563
6564         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6565         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6566
6567         return skinframe;
6568 }
6569
6570 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6571 {
6572         int i;
6573         int featuresmask;
6574         skinframe_t *skinframe;
6575
6576         if (cls.state == ca_dedicated)
6577                 return NULL;
6578
6579         // if already loaded just return it, otherwise make a new skinframe
6580         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6581         if (skinframe && skinframe->base)
6582                 return skinframe;
6583
6584         skinframe->stain = NULL;
6585         skinframe->merged = NULL;
6586         skinframe->base = NULL;
6587         skinframe->pants = NULL;
6588         skinframe->shirt = NULL;
6589         skinframe->nmap = NULL;
6590         skinframe->gloss = NULL;
6591         skinframe->glow = NULL;
6592         skinframe->fog = NULL;
6593         skinframe->reflect = NULL;
6594         skinframe->hasalpha = false;
6595
6596         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6597         if (!skindata)
6598                 return NULL;
6599
6600         if (developer_loading.integer)
6601                 Con_Printf("loading quake skin \"%s\"\n", name);
6602
6603         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6604         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6605         memcpy(skinframe->qpixels, skindata, width*height);
6606         skinframe->qwidth = width;
6607         skinframe->qheight = height;
6608
6609         featuresmask = 0;
6610         for (i = 0;i < width * height;i++)
6611                 featuresmask |= palette_featureflags[skindata[i]];
6612
6613         skinframe->hasalpha = false;
6614         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6615         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6616         skinframe->qgeneratemerged = true;
6617         skinframe->qgeneratebase = skinframe->qhascolormapping;
6618         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6619
6620         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6621         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6622
6623         return skinframe;
6624 }
6625
6626 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6627 {
6628         int width;
6629         int height;
6630         unsigned char *skindata;
6631
6632         if (!skinframe->qpixels)
6633                 return;
6634
6635         if (!skinframe->qhascolormapping)
6636                 colormapped = false;
6637
6638         if (colormapped)
6639         {
6640                 if (!skinframe->qgeneratebase)
6641                         return;
6642         }
6643         else
6644         {
6645                 if (!skinframe->qgeneratemerged)
6646                         return;
6647         }
6648
6649         width = skinframe->qwidth;
6650         height = skinframe->qheight;
6651         skindata = skinframe->qpixels;
6652
6653         if (skinframe->qgeneratenmap)
6654         {
6655                 unsigned char *temp1, *temp2;
6656                 skinframe->qgeneratenmap = false;
6657                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6658                 temp2 = temp1 + width * height * 4;
6659                 // use either a custom palette or the quake palette
6660                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6661                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6662                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6663                 Mem_Free(temp1);
6664         }
6665
6666         if (skinframe->qgenerateglow)
6667         {
6668                 skinframe->qgenerateglow = false;
6669                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6670         }
6671
6672         if (colormapped)
6673         {
6674                 skinframe->qgeneratebase = false;
6675                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6676                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6677                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6678         }
6679         else
6680         {
6681                 skinframe->qgeneratemerged = false;
6682                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6683         }
6684
6685         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6686         {
6687                 Mem_Free(skinframe->qpixels);
6688                 skinframe->qpixels = NULL;
6689         }
6690 }
6691
6692 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6693 {
6694         int i;
6695         skinframe_t *skinframe;
6696
6697         if (cls.state == ca_dedicated)
6698                 return NULL;
6699
6700         // if already loaded just return it, otherwise make a new skinframe
6701         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6702         if (skinframe && skinframe->base)
6703                 return skinframe;
6704
6705         skinframe->stain = NULL;
6706         skinframe->merged = NULL;
6707         skinframe->base = NULL;
6708         skinframe->pants = NULL;
6709         skinframe->shirt = NULL;
6710         skinframe->nmap = NULL;
6711         skinframe->gloss = NULL;
6712         skinframe->glow = NULL;
6713         skinframe->fog = NULL;
6714         skinframe->reflect = NULL;
6715         skinframe->hasalpha = false;
6716
6717         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6718         if (!skindata)
6719                 return NULL;
6720
6721         if (developer_loading.integer)
6722                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6723
6724         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6725         if (textureflags & TEXF_ALPHA)
6726         {
6727                 for (i = 0;i < width * height;i++)
6728                 {
6729                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6730                         {
6731                                 skinframe->hasalpha = true;
6732                                 break;
6733                         }
6734                 }
6735                 if (r_loadfog && skinframe->hasalpha)
6736                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6737         }
6738
6739         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6740         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6741
6742         return skinframe;
6743 }
6744
6745 skinframe_t *R_SkinFrame_LoadMissing(void)
6746 {
6747         skinframe_t *skinframe;
6748
6749         if (cls.state == ca_dedicated)
6750                 return NULL;
6751
6752         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6753         skinframe->stain = NULL;
6754         skinframe->merged = NULL;
6755         skinframe->base = NULL;
6756         skinframe->pants = NULL;
6757         skinframe->shirt = NULL;
6758         skinframe->nmap = NULL;
6759         skinframe->gloss = NULL;
6760         skinframe->glow = NULL;
6761         skinframe->fog = NULL;
6762         skinframe->reflect = NULL;
6763         skinframe->hasalpha = false;
6764
6765         skinframe->avgcolor[0] = rand() / RAND_MAX;
6766         skinframe->avgcolor[1] = rand() / RAND_MAX;
6767         skinframe->avgcolor[2] = rand() / RAND_MAX;
6768         skinframe->avgcolor[3] = 1;
6769
6770         return skinframe;
6771 }
6772
6773 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6774 typedef struct suffixinfo_s
6775 {
6776         const char *suffix;
6777         qboolean flipx, flipy, flipdiagonal;
6778 }
6779 suffixinfo_t;
6780 static suffixinfo_t suffix[3][6] =
6781 {
6782         {
6783                 {"px",   false, false, false},
6784                 {"nx",   false, false, false},
6785                 {"py",   false, false, false},
6786                 {"ny",   false, false, false},
6787                 {"pz",   false, false, false},
6788                 {"nz",   false, false, false}
6789         },
6790         {
6791                 {"posx", false, false, false},
6792                 {"negx", false, false, false},
6793                 {"posy", false, false, false},
6794                 {"negy", false, false, false},
6795                 {"posz", false, false, false},
6796                 {"negz", false, false, false}
6797         },
6798         {
6799                 {"rt",    true, false,  true},
6800                 {"lf",   false,  true,  true},
6801                 {"ft",    true,  true, false},
6802                 {"bk",   false, false, false},
6803                 {"up",    true, false,  true},
6804                 {"dn",    true, false,  true}
6805         }
6806 };
6807
6808 static int componentorder[4] = {0, 1, 2, 3};
6809
6810 rtexture_t *R_LoadCubemap(const char *basename)
6811 {
6812         int i, j, cubemapsize;
6813         unsigned char *cubemappixels, *image_buffer;
6814         rtexture_t *cubemaptexture;
6815         char name[256];
6816         // must start 0 so the first loadimagepixels has no requested width/height
6817         cubemapsize = 0;
6818         cubemappixels = NULL;
6819         cubemaptexture = NULL;
6820         // keep trying different suffix groups (posx, px, rt) until one loads
6821         for (j = 0;j < 3 && !cubemappixels;j++)
6822         {
6823                 // load the 6 images in the suffix group
6824                 for (i = 0;i < 6;i++)
6825                 {
6826                         // generate an image name based on the base and and suffix
6827                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6828                         // load it
6829                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6830                         {
6831                                 // an image loaded, make sure width and height are equal
6832                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6833                                 {
6834                                         // if this is the first image to load successfully, allocate the cubemap memory
6835                                         if (!cubemappixels && image_width >= 1)
6836                                         {
6837                                                 cubemapsize = image_width;
6838                                                 // note this clears to black, so unavailable sides are black
6839                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6840                                         }
6841                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6842                                         if (cubemappixels)
6843                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
6844                                 }
6845                                 else
6846                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6847                                 // free the image
6848                                 Mem_Free(image_buffer);
6849                         }
6850                 }
6851         }
6852         // if a cubemap loaded, upload it
6853         if (cubemappixels)
6854         {
6855                 if (developer_loading.integer)
6856                         Con_Printf("loading cubemap \"%s\"\n", basename);
6857
6858                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6859                 Mem_Free(cubemappixels);
6860         }
6861         else
6862         {
6863                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6864                 if (developer_loading.integer)
6865                 {
6866                         Con_Printf("(tried tried images ");
6867                         for (j = 0;j < 3;j++)
6868                                 for (i = 0;i < 6;i++)
6869                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6870                         Con_Print(" and was unable to find any of them).\n");
6871                 }
6872         }
6873         return cubemaptexture;
6874 }
6875
6876 rtexture_t *R_GetCubemap(const char *basename)
6877 {
6878         int i;
6879         for (i = 0;i < r_texture_numcubemaps;i++)
6880                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6881                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6882         if (i >= MAX_CUBEMAPS)
6883                 return r_texture_whitecube;
6884         r_texture_numcubemaps++;
6885         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6886         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6887         return r_texture_cubemaps[i].texture;
6888 }
6889
6890 void R_FreeCubemaps(void)
6891 {
6892         int i;
6893         for (i = 0;i < r_texture_numcubemaps;i++)
6894         {
6895                 if (developer_loading.integer)
6896                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6897                 if (r_texture_cubemaps[i].texture)
6898                         R_FreeTexture(r_texture_cubemaps[i].texture);
6899         }
6900         r_texture_numcubemaps = 0;
6901 }
6902
6903 void R_Main_FreeViewCache(void)
6904 {
6905         if (r_refdef.viewcache.entityvisible)
6906                 Mem_Free(r_refdef.viewcache.entityvisible);
6907         if (r_refdef.viewcache.world_pvsbits)
6908                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6909         if (r_refdef.viewcache.world_leafvisible)
6910                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6911         if (r_refdef.viewcache.world_surfacevisible)
6912                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6913         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6914 }
6915
6916 void R_Main_ResizeViewCache(void)
6917 {
6918         int numentities = r_refdef.scene.numentities;
6919         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6920         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6921         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6922         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6923         if (r_refdef.viewcache.maxentities < numentities)
6924         {
6925                 r_refdef.viewcache.maxentities = numentities;
6926                 if (r_refdef.viewcache.entityvisible)
6927                         Mem_Free(r_refdef.viewcache.entityvisible);
6928                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6929         }
6930         if (r_refdef.viewcache.world_numclusters != numclusters)
6931         {
6932                 r_refdef.viewcache.world_numclusters = numclusters;
6933                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6934                 if (r_refdef.viewcache.world_pvsbits)
6935                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6936                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6937         }
6938         if (r_refdef.viewcache.world_numleafs != numleafs)
6939         {
6940                 r_refdef.viewcache.world_numleafs = numleafs;
6941                 if (r_refdef.viewcache.world_leafvisible)
6942                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6943                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6944         }
6945         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6946         {
6947                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6948                 if (r_refdef.viewcache.world_surfacevisible)
6949                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6950                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6951         }
6952 }
6953
6954 extern rtexture_t *loadingscreentexture;
6955 void gl_main_start(void)
6956 {
6957         loadingscreentexture = NULL;
6958         r_texture_blanknormalmap = NULL;
6959         r_texture_white = NULL;
6960         r_texture_grey128 = NULL;
6961         r_texture_black = NULL;
6962         r_texture_whitecube = NULL;
6963         r_texture_normalizationcube = NULL;
6964         r_texture_fogattenuation = NULL;
6965         r_texture_fogheighttexture = NULL;
6966         r_texture_gammaramps = NULL;
6967         r_texture_numcubemaps = 0;
6968
6969         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6970         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6971
6972         switch(vid.renderpath)
6973         {
6974         case RENDERPATH_GL20:
6975         case RENDERPATH_CGGL:
6976         case RENDERPATH_D3D9:
6977         case RENDERPATH_D3D10:
6978         case RENDERPATH_D3D11:
6979                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6980                 Cvar_SetValueQuick(&gl_combine, 1);
6981                 Cvar_SetValueQuick(&r_glsl, 1);
6982                 r_loadnormalmap = true;
6983                 r_loadgloss = true;
6984                 r_loadfog = false;
6985                 break;
6986         case RENDERPATH_GL13:
6987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6988                 Cvar_SetValueQuick(&gl_combine, 1);
6989                 Cvar_SetValueQuick(&r_glsl, 0);
6990                 r_loadnormalmap = false;
6991                 r_loadgloss = false;
6992                 r_loadfog = true;
6993                 break;
6994         case RENDERPATH_GL11:
6995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6996                 Cvar_SetValueQuick(&gl_combine, 0);
6997                 Cvar_SetValueQuick(&r_glsl, 0);
6998                 r_loadnormalmap = false;
6999                 r_loadgloss = false;
7000                 r_loadfog = true;
7001                 break;
7002         }
7003
7004         R_AnimCache_Free();
7005         R_FrameData_Reset();
7006
7007         r_numqueries = 0;
7008         r_maxqueries = 0;
7009         memset(r_queries, 0, sizeof(r_queries));
7010
7011         r_qwskincache = NULL;
7012         r_qwskincache_size = 0;
7013
7014         // set up r_skinframe loading system for textures
7015         memset(&r_skinframe, 0, sizeof(r_skinframe));
7016         r_skinframe.loadsequence = 1;
7017         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7018
7019         r_main_texturepool = R_AllocTexturePool();
7020         R_BuildBlankTextures();
7021         R_BuildNoTexture();
7022         if (vid.support.arb_texture_cube_map)
7023         {
7024                 R_BuildWhiteCube();
7025                 R_BuildNormalizationCube();
7026         }
7027         r_texture_fogattenuation = NULL;
7028         r_texture_fogheighttexture = NULL;
7029         r_texture_gammaramps = NULL;
7030         //r_texture_fogintensity = NULL;
7031         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7032         memset(&r_waterstate, 0, sizeof(r_waterstate));
7033         r_glsl_permutation = NULL;
7034         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7035         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7036         glslshaderstring = NULL;
7037 #ifdef SUPPORTCG
7038         r_cg_permutation = NULL;
7039         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7040         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7041         cgshaderstring = NULL;
7042 #endif
7043 #ifdef SUPPORTD3D
7044         r_hlsl_permutation = NULL;
7045         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7046         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7047         hlslshaderstring = NULL;
7048 #endif
7049         memset(&r_svbsp, 0, sizeof (r_svbsp));
7050
7051         r_refdef.fogmasktable_density = 0;
7052 }
7053
7054 void gl_main_shutdown(void)
7055 {
7056         R_AnimCache_Free();
7057         R_FrameData_Reset();
7058
7059         R_Main_FreeViewCache();
7060
7061         switch(vid.renderpath)
7062         {
7063         case RENDERPATH_GL11:
7064         case RENDERPATH_GL13:
7065         case RENDERPATH_GL20:
7066         case RENDERPATH_CGGL:
7067                 if (r_maxqueries)
7068                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7069                 break;
7070         case RENDERPATH_D3D9:
7071                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7072                 break;
7073         case RENDERPATH_D3D10:
7074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7075                 break;
7076         case RENDERPATH_D3D11:
7077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7078                 break;
7079         }
7080
7081         r_numqueries = 0;
7082         r_maxqueries = 0;
7083         memset(r_queries, 0, sizeof(r_queries));
7084
7085         r_qwskincache = NULL;
7086         r_qwskincache_size = 0;
7087
7088         // clear out the r_skinframe state
7089         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7090         memset(&r_skinframe, 0, sizeof(r_skinframe));
7091
7092         if (r_svbsp.nodes)
7093                 Mem_Free(r_svbsp.nodes);
7094         memset(&r_svbsp, 0, sizeof (r_svbsp));
7095         R_FreeTexturePool(&r_main_texturepool);
7096         loadingscreentexture = NULL;
7097         r_texture_blanknormalmap = NULL;
7098         r_texture_white = NULL;
7099         r_texture_grey128 = NULL;
7100         r_texture_black = NULL;
7101         r_texture_whitecube = NULL;
7102         r_texture_normalizationcube = NULL;
7103         r_texture_fogattenuation = NULL;
7104         r_texture_fogheighttexture = NULL;
7105         r_texture_gammaramps = NULL;
7106         r_texture_numcubemaps = 0;
7107         //r_texture_fogintensity = NULL;
7108         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7109         memset(&r_waterstate, 0, sizeof(r_waterstate));
7110         R_GLSL_Restart_f();
7111 }
7112
7113 extern void CL_ParseEntityLump(char *entitystring);
7114 void gl_main_newmap(void)
7115 {
7116         // FIXME: move this code to client
7117         char *entities, entname[MAX_QPATH];
7118         if (r_qwskincache)
7119                 Mem_Free(r_qwskincache);
7120         r_qwskincache = NULL;
7121         r_qwskincache_size = 0;
7122         if (cl.worldmodel)
7123         {
7124                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7125                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7126                 {
7127                         CL_ParseEntityLump(entities);
7128                         Mem_Free(entities);
7129                         return;
7130                 }
7131                 if (cl.worldmodel->brush.entities)
7132                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7133         }
7134         R_Main_FreeViewCache();
7135
7136         R_FrameData_Reset();
7137 }
7138
7139 void GL_Main_Init(void)
7140 {
7141         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7142
7143         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7144         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7145         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7146         if (gamemode == GAME_NEHAHRA)
7147         {
7148                 Cvar_RegisterVariable (&gl_fogenable);
7149                 Cvar_RegisterVariable (&gl_fogdensity);
7150                 Cvar_RegisterVariable (&gl_fogred);
7151                 Cvar_RegisterVariable (&gl_foggreen);
7152                 Cvar_RegisterVariable (&gl_fogblue);
7153                 Cvar_RegisterVariable (&gl_fogstart);
7154                 Cvar_RegisterVariable (&gl_fogend);
7155                 Cvar_RegisterVariable (&gl_skyclip);
7156         }
7157         Cvar_RegisterVariable(&r_motionblur);
7158         Cvar_RegisterVariable(&r_motionblur_maxblur);
7159         Cvar_RegisterVariable(&r_motionblur_bmin);
7160         Cvar_RegisterVariable(&r_motionblur_vmin);
7161         Cvar_RegisterVariable(&r_motionblur_vmax);
7162         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7163         Cvar_RegisterVariable(&r_motionblur_randomize);
7164         Cvar_RegisterVariable(&r_damageblur);
7165         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7166         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7167         Cvar_RegisterVariable(&r_equalize_entities_by);
7168         Cvar_RegisterVariable(&r_equalize_entities_to);
7169         Cvar_RegisterVariable(&r_depthfirst);
7170         Cvar_RegisterVariable(&r_useinfinitefarclip);
7171         Cvar_RegisterVariable(&r_farclip_base);
7172         Cvar_RegisterVariable(&r_farclip_world);
7173         Cvar_RegisterVariable(&r_nearclip);
7174         Cvar_RegisterVariable(&r_showbboxes);
7175         Cvar_RegisterVariable(&r_showsurfaces);
7176         Cvar_RegisterVariable(&r_showtris);
7177         Cvar_RegisterVariable(&r_shownormals);
7178         Cvar_RegisterVariable(&r_showlighting);
7179         Cvar_RegisterVariable(&r_showshadowvolumes);
7180         Cvar_RegisterVariable(&r_showcollisionbrushes);
7181         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7182         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7183         Cvar_RegisterVariable(&r_showdisabledepthtest);
7184         Cvar_RegisterVariable(&r_drawportals);
7185         Cvar_RegisterVariable(&r_drawentities);
7186         Cvar_RegisterVariable(&r_draw2d);
7187         Cvar_RegisterVariable(&r_drawworld);
7188         Cvar_RegisterVariable(&r_cullentities_trace);
7189         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7190         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7191         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7192         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7193         Cvar_RegisterVariable(&r_drawviewmodel);
7194         Cvar_RegisterVariable(&r_drawexteriormodel);
7195         Cvar_RegisterVariable(&r_speeds);
7196         Cvar_RegisterVariable(&r_fullbrights);
7197         Cvar_RegisterVariable(&r_wateralpha);
7198         Cvar_RegisterVariable(&r_dynamic);
7199         Cvar_RegisterVariable(&r_fullbright);
7200         Cvar_RegisterVariable(&r_shadows);
7201         Cvar_RegisterVariable(&r_shadows_darken);
7202         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7203         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7204         Cvar_RegisterVariable(&r_shadows_throwdistance);
7205         Cvar_RegisterVariable(&r_shadows_throwdirection);
7206         Cvar_RegisterVariable(&r_shadows_focus);
7207         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7208         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7209         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7210         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7211         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7212         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7213         Cvar_RegisterVariable(&r_fog_exp2);
7214         Cvar_RegisterVariable(&r_drawfog);
7215         Cvar_RegisterVariable(&r_transparentdepthmasking);
7216         Cvar_RegisterVariable(&r_texture_dds_load);
7217         Cvar_RegisterVariable(&r_texture_dds_save);
7218         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7219         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7220         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7221         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7222         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7223         Cvar_RegisterVariable(&r_textureunits);
7224         Cvar_RegisterVariable(&gl_combine);
7225         Cvar_RegisterVariable(&r_glsl);
7226         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7227         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7228         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7229         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7230         Cvar_RegisterVariable(&r_glsl_postprocess);
7231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7235         Cvar_RegisterVariable(&r_water);
7236         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7237         Cvar_RegisterVariable(&r_water_clippingplanebias);
7238         Cvar_RegisterVariable(&r_water_refractdistort);
7239         Cvar_RegisterVariable(&r_water_reflectdistort);
7240         Cvar_RegisterVariable(&r_lerpsprites);
7241         Cvar_RegisterVariable(&r_lerpmodels);
7242         Cvar_RegisterVariable(&r_lerplightstyles);
7243         Cvar_RegisterVariable(&r_waterscroll);
7244         Cvar_RegisterVariable(&r_bloom);
7245         Cvar_RegisterVariable(&r_bloom_colorscale);
7246         Cvar_RegisterVariable(&r_bloom_brighten);
7247         Cvar_RegisterVariable(&r_bloom_blur);
7248         Cvar_RegisterVariable(&r_bloom_resolution);
7249         Cvar_RegisterVariable(&r_bloom_colorexponent);
7250         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7251         Cvar_RegisterVariable(&r_hdr);
7252         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7253         Cvar_RegisterVariable(&r_hdr_glowintensity);
7254         Cvar_RegisterVariable(&r_hdr_range);
7255         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7256         Cvar_RegisterVariable(&developer_texturelogging);
7257         Cvar_RegisterVariable(&gl_lightmaps);
7258         Cvar_RegisterVariable(&r_test);
7259         Cvar_RegisterVariable(&r_glsl_saturation);
7260         Cvar_RegisterVariable(&r_framedatasize);
7261         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7262                 Cvar_SetValue("r_fullbrights", 0);
7263         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7264
7265         Cvar_RegisterVariable(&r_track_sprites);
7266         Cvar_RegisterVariable(&r_track_sprites_flags);
7267         Cvar_RegisterVariable(&r_track_sprites_scalew);
7268         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7269         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7270         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7271 }
7272
7273 extern void R_Textures_Init(void);
7274 extern void GL_Draw_Init(void);
7275 extern void GL_Main_Init(void);
7276 extern void R_Shadow_Init(void);
7277 extern void R_Sky_Init(void);
7278 extern void GL_Surf_Init(void);
7279 extern void R_Particles_Init(void);
7280 extern void R_Explosion_Init(void);
7281 extern void gl_backend_init(void);
7282 extern void Sbar_Init(void);
7283 extern void R_LightningBeams_Init(void);
7284 extern void Mod_RenderInit(void);
7285 extern void Font_Init(void);
7286
7287 void Render_Init(void)
7288 {
7289         gl_backend_init();
7290         R_Textures_Init();
7291         GL_Main_Init();
7292         Font_Init();
7293         GL_Draw_Init();
7294         R_Shadow_Init();
7295         R_Sky_Init();
7296         GL_Surf_Init();
7297         Sbar_Init();
7298         R_Particles_Init();
7299         R_Explosion_Init();
7300         R_LightningBeams_Init();
7301         Mod_RenderInit();
7302 }
7303
7304 /*
7305 ===============
7306 GL_Init
7307 ===============
7308 */
7309 extern char *ENGINE_EXTENSIONS;
7310 void GL_Init (void)
7311 {
7312         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7313         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7314         gl_version = (const char *)qglGetString(GL_VERSION);
7315         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7316
7317         if (!gl_extensions)
7318                 gl_extensions = "";
7319         if (!gl_platformextensions)
7320                 gl_platformextensions = "";
7321
7322         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7323         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7324         Con_Printf("GL_VERSION: %s\n", gl_version);
7325         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7326         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7327
7328         VID_CheckExtensions();
7329
7330         // LordHavoc: report supported extensions
7331         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7332
7333         // clear to black (loading plaque will be seen over this)
7334         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7335 }
7336
7337 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7338 {
7339         int i;
7340         mplane_t *p;
7341         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7342         {
7343                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7344                 if (i == 4)
7345                         continue;
7346                 p = r_refdef.view.frustum + i;
7347                 switch(p->signbits)
7348                 {
7349                 default:
7350                 case 0:
7351                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7352                                 return true;
7353                         break;
7354                 case 1:
7355                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7356                                 return true;
7357                         break;
7358                 case 2:
7359                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7360                                 return true;
7361                         break;
7362                 case 3:
7363                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7364                                 return true;
7365                         break;
7366                 case 4:
7367                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7368                                 return true;
7369                         break;
7370                 case 5:
7371                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7372                                 return true;
7373                         break;
7374                 case 6:
7375                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7376                                 return true;
7377                         break;
7378                 case 7:
7379                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7380                                 return true;
7381                         break;
7382                 }
7383         }
7384         return false;
7385 }
7386
7387 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7388 {
7389         int i;
7390         const mplane_t *p;
7391         for (i = 0;i < numplanes;i++)
7392         {
7393                 p = planes + i;
7394                 switch(p->signbits)
7395                 {
7396                 default:
7397                 case 0:
7398                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7399                                 return true;
7400                         break;
7401                 case 1:
7402                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7403                                 return true;
7404                         break;
7405                 case 2:
7406                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7407                                 return true;
7408                         break;
7409                 case 3:
7410                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7411                                 return true;
7412                         break;
7413                 case 4:
7414                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7415                                 return true;
7416                         break;
7417                 case 5:
7418                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7419                                 return true;
7420                         break;
7421                 case 6:
7422                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7423                                 return true;
7424                         break;
7425                 case 7:
7426                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7427                                 return true;
7428                         break;
7429                 }
7430         }
7431         return false;
7432 }
7433
7434 //==================================================================================
7435
7436 // LordHavoc: this stores temporary data used within the same frame
7437
7438 qboolean r_framedata_failed;
7439 static size_t r_framedata_size;
7440 static size_t r_framedata_current;
7441 static void *r_framedata_base;
7442
7443 void R_FrameData_Reset(void)
7444 {
7445         if (r_framedata_base)
7446                 Mem_Free(r_framedata_base);
7447         r_framedata_base = NULL;
7448         r_framedata_size = 0;
7449         r_framedata_current = 0;
7450         r_framedata_failed = false;
7451 }
7452
7453 void R_FrameData_NewFrame(void)
7454 {
7455         size_t wantedsize;
7456         if (r_framedata_failed)
7457                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7458         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7459         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7460         if (r_framedata_size != wantedsize)
7461         {
7462                 r_framedata_size = wantedsize;
7463                 if (r_framedata_base)
7464                         Mem_Free(r_framedata_base);
7465                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7466         }
7467         r_framedata_current = 0;
7468         r_framedata_failed = false;
7469 }
7470
7471 void *R_FrameData_Alloc(size_t size)
7472 {
7473         void *data;
7474
7475         // align to 16 byte boundary
7476         size = (size + 15) & ~15;
7477         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7478         r_framedata_current += size;
7479
7480         // check overflow
7481         if (r_framedata_current > r_framedata_size)
7482                 r_framedata_failed = true;
7483
7484         // return NULL on everything after a failure
7485         if (r_framedata_failed)
7486                 return NULL;
7487
7488         return data;
7489 }
7490
7491 void *R_FrameData_Store(size_t size, void *data)
7492 {
7493         void *d = R_FrameData_Alloc(size);
7494         if (d)
7495                 memcpy(d, data, size);
7496         return d;
7497 }
7498
7499 //==================================================================================
7500
7501 // LordHavoc: animcache originally written by Echon, rewritten since then
7502
7503 /**
7504  * Animation cache prevents re-generating mesh data for an animated model
7505  * multiple times in one frame for lighting, shadowing, reflections, etc.
7506  */
7507
7508 void R_AnimCache_Free(void)
7509 {
7510 }
7511
7512 void R_AnimCache_ClearCache(void)
7513 {
7514         int i;
7515         entity_render_t *ent;
7516
7517         for (i = 0;i < r_refdef.scene.numentities;i++)
7518         {
7519                 ent = r_refdef.scene.entities[i];
7520                 ent->animcache_vertex3f = NULL;
7521                 ent->animcache_normal3f = NULL;
7522                 ent->animcache_svector3f = NULL;
7523                 ent->animcache_tvector3f = NULL;
7524                 ent->animcache_vertexposition = NULL;
7525                 ent->animcache_vertexmesh = NULL;
7526                 ent->animcache_vertexpositionbuffer = NULL;
7527                 ent->animcache_vertexmeshbuffer = NULL;
7528         }
7529 }
7530
7531 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7532 {
7533         int i;
7534
7535         // identical memory layout, so no need to allocate...
7536         // this also provides the vertexposition structure to everything, e.g.
7537         // depth masked rendering currently uses it even if having separate
7538         // arrays
7539         // NOTE: get rid of this optimization if changing it to e.g. 4f
7540         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7541
7542         // TODO:
7543         // get rid of following uses of VERTEXPOSITION, change to the array:
7544         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7545         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7546         // R_DrawTextureSurfaceList_DepthOnly
7547         // R_Q1BSP_DrawShadowMap
7548
7549         switch(vid.renderpath)
7550         {
7551         case RENDERPATH_GL20:
7552         case RENDERPATH_CGGL:
7553                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7554                 if (gl_mesh_separatearrays.integer)
7555                         return;
7556                 break;
7557         case RENDERPATH_D3D9:
7558         case RENDERPATH_D3D10:
7559         case RENDERPATH_D3D11:
7560                 // always need the meshbuffers
7561                 break;
7562         case RENDERPATH_GL13:
7563         case RENDERPATH_GL11:
7564                 // never need the meshbuffers
7565                 return;
7566         }
7567
7568         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7569                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7570         /*
7571         if (!ent->animcache_vertexposition)
7572                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7573         */
7574         if (ent->animcache_vertexposition)
7575         {
7576                 /*
7577                 for (i = 0;i < numvertices;i++)
7578                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7579                 */
7580                 // TODO: upload vertex buffer?
7581         }
7582         if (ent->animcache_vertexmesh)
7583         {
7584                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7585                 for (i = 0;i < numvertices;i++)
7586                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7587                 if (ent->animcache_svector3f)
7588                         for (i = 0;i < numvertices;i++)
7589                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7590                 if (ent->animcache_tvector3f)
7591                         for (i = 0;i < numvertices;i++)
7592                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7593                 if (ent->animcache_normal3f)
7594                         for (i = 0;i < numvertices;i++)
7595                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7596                 // TODO: upload vertex buffer?
7597         }
7598 }
7599
7600 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7601 {
7602         dp_model_t *model = ent->model;
7603         int numvertices;
7604         // see if it's already cached this frame
7605         if (ent->animcache_vertex3f)
7606         {
7607                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7608                 if (wantnormals || wanttangents)
7609                 {
7610                         if (ent->animcache_normal3f)
7611                                 wantnormals = false;
7612                         if (ent->animcache_svector3f)
7613                                 wanttangents = false;
7614                         if (wantnormals || wanttangents)
7615                         {
7616                                 numvertices = model->surfmesh.num_vertices;
7617                                 if (wantnormals)
7618                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7619                                 if (wanttangents)
7620                                 {
7621                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7622                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7623                                 }
7624                                 if (!r_framedata_failed)
7625                                 {
7626                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7627                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7628                                 }
7629                         }
7630                 }
7631         }
7632         else
7633         {
7634                 // see if this ent is worth caching
7635                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7636                         return false;
7637                 // get some memory for this entity and generate mesh data
7638                 numvertices = model->surfmesh.num_vertices;
7639                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7640                 if (wantnormals)
7641                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7642                 if (wanttangents)
7643                 {
7644                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7645                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7646                 }
7647                 if (!r_framedata_failed)
7648                 {
7649                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7650                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7651                 }
7652         }
7653         return !r_framedata_failed;
7654 }
7655
7656 void R_AnimCache_CacheVisibleEntities(void)
7657 {
7658         int i;
7659         qboolean wantnormals = true;
7660         qboolean wanttangents = !r_showsurfaces.integer;
7661
7662         switch(vid.renderpath)
7663         {
7664         case RENDERPATH_GL20:
7665         case RENDERPATH_CGGL:
7666         case RENDERPATH_D3D9:
7667         case RENDERPATH_D3D10:
7668         case RENDERPATH_D3D11:
7669                 break;
7670         case RENDERPATH_GL13:
7671         case RENDERPATH_GL11:
7672                 wanttangents = false;
7673                 break;
7674         }
7675
7676         if (r_shownormals.integer)
7677                 wanttangents = wantnormals = true;
7678
7679         // TODO: thread this
7680         // NOTE: R_PrepareRTLights() also caches entities
7681
7682         for (i = 0;i < r_refdef.scene.numentities;i++)
7683                 if (r_refdef.viewcache.entityvisible[i])
7684                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7685 }
7686
7687 //==================================================================================
7688
7689 static void R_View_UpdateEntityLighting (void)
7690 {
7691         int i;
7692         entity_render_t *ent;
7693         vec3_t tempdiffusenormal, avg;
7694         vec_t f, fa, fd, fdd;
7695         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7696
7697         for (i = 0;i < r_refdef.scene.numentities;i++)
7698         {
7699                 ent = r_refdef.scene.entities[i];
7700
7701                 // skip unseen models
7702                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7703                         continue;
7704
7705                 // skip bsp models
7706                 if (ent->model && ent->model->brush.num_leafs)
7707                 {
7708                         // TODO: use modellight for r_ambient settings on world?
7709                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7710                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7711                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7712                         continue;
7713                 }
7714
7715                 // fetch the lighting from the worldmodel data
7716                 VectorClear(ent->modellight_ambient);
7717                 VectorClear(ent->modellight_diffuse);
7718                 VectorClear(tempdiffusenormal);
7719                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7720                 {
7721                         vec3_t org;
7722                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7723                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7724                         if(ent->flags & RENDER_EQUALIZE)
7725                         {
7726                                 // first fix up ambient lighting...
7727                                 if(r_equalize_entities_minambient.value > 0)
7728                                 {
7729                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7730                                         if(fd > 0)
7731                                         {
7732                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7733                                                 if(fa < r_equalize_entities_minambient.value * fd)
7734                                                 {
7735                                                         // solve:
7736                                                         //   fa'/fd' = minambient
7737                                                         //   fa'+0.25*fd' = fa+0.25*fd
7738                                                         //   ...
7739                                                         //   fa' = fd' * minambient
7740                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7741                                                         //   ...
7742                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7743                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7744                                                         //   ...
7745                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7746                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
7747                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7748                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7749                                                 }
7750                                         }
7751                                 }
7752
7753                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7754                                 {
7755                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7756                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7757                                         if(f > 0)
7758                                         {
7759                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7760                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7761                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7762                                         }
7763                                 }
7764                         }
7765                 }
7766                 else // highly rare
7767                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7768
7769                 // move the light direction into modelspace coordinates for lighting code
7770                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7771                 if(VectorLength2(ent->modellight_lightdir) == 0)
7772                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7773                 VectorNormalize(ent->modellight_lightdir);
7774         }
7775 }
7776
7777 #define MAX_LINEOFSIGHTTRACES 64
7778
7779 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7780 {
7781         int i;
7782         vec3_t boxmins, boxmaxs;
7783         vec3_t start;
7784         vec3_t end;
7785         dp_model_t *model = r_refdef.scene.worldmodel;
7786
7787         if (!model || !model->brush.TraceLineOfSight)
7788                 return true;
7789
7790         // expand the box a little
7791         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7792         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7793         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7794         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7795         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7796         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7797
7798         // return true if eye is inside enlarged box
7799         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7800                 return true;
7801
7802         // try center
7803         VectorCopy(eye, start);
7804         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7805         if (model->brush.TraceLineOfSight(model, start, end))
7806                 return true;
7807
7808         // try various random positions
7809         for (i = 0;i < numsamples;i++)
7810         {
7811                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7812                 if (model->brush.TraceLineOfSight(model, start, end))
7813                         return true;
7814         }
7815
7816         return false;
7817 }
7818
7819
7820 static void R_View_UpdateEntityVisible (void)
7821 {
7822         int i;
7823         int renderimask;
7824         int samples;
7825         entity_render_t *ent;
7826
7827         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7828                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7829                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7830                 :                                                          RENDER_EXTERIORMODEL;
7831         if (!r_drawviewmodel.integer)
7832                 renderimask |= RENDER_VIEWMODEL;
7833         if (!r_drawexteriormodel.integer)
7834                 renderimask |= RENDER_EXTERIORMODEL;
7835         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7836         {
7837                 // worldmodel can check visibility
7838                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7839                 for (i = 0;i < r_refdef.scene.numentities;i++)
7840                 {
7841                         ent = r_refdef.scene.entities[i];
7842                         if (!(ent->flags & renderimask))
7843                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7844                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
7845                                 r_refdef.viewcache.entityvisible[i] = true;
7846                 }
7847                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7848                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7849                 {
7850                         for (i = 0;i < r_refdef.scene.numentities;i++)
7851                         {
7852                                 ent = r_refdef.scene.entities[i];
7853                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7854                                 {
7855                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7856                                         if (samples < 0)
7857                                                 continue; // temp entities do pvs only
7858                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7859                                                 ent->last_trace_visibility = realtime;
7860                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7861                                                 r_refdef.viewcache.entityvisible[i] = 0;
7862                                 }
7863                         }
7864                 }
7865         }
7866         else
7867         {
7868                 // no worldmodel or it can't check visibility
7869                 for (i = 0;i < r_refdef.scene.numentities;i++)
7870                 {
7871                         ent = r_refdef.scene.entities[i];
7872                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
7873                 }
7874         }
7875 }
7876
7877 /// only used if skyrendermasked, and normally returns false
7878 int R_DrawBrushModelsSky (void)
7879 {
7880         int i, sky;
7881         entity_render_t *ent;
7882
7883         sky = false;
7884         for (i = 0;i < r_refdef.scene.numentities;i++)
7885         {
7886                 if (!r_refdef.viewcache.entityvisible[i])
7887                         continue;
7888                 ent = r_refdef.scene.entities[i];
7889                 if (!ent->model || !ent->model->DrawSky)
7890                         continue;
7891                 ent->model->DrawSky(ent);
7892                 sky = true;
7893         }
7894         return sky;
7895 }
7896
7897 static void R_DrawNoModel(entity_render_t *ent);
7898 static void R_DrawModels(void)
7899 {
7900         int i;
7901         entity_render_t *ent;
7902
7903         for (i = 0;i < r_refdef.scene.numentities;i++)
7904         {
7905                 if (!r_refdef.viewcache.entityvisible[i])
7906                         continue;
7907                 ent = r_refdef.scene.entities[i];
7908                 r_refdef.stats.entities++;
7909                 if (ent->model && ent->model->Draw != NULL)
7910                         ent->model->Draw(ent);
7911                 else
7912                         R_DrawNoModel(ent);
7913         }
7914 }
7915
7916 static void R_DrawModelsDepth(void)
7917 {
7918         int i;
7919         entity_render_t *ent;
7920
7921         for (i = 0;i < r_refdef.scene.numentities;i++)
7922         {
7923                 if (!r_refdef.viewcache.entityvisible[i])
7924                         continue;
7925                 ent = r_refdef.scene.entities[i];
7926                 if (ent->model && ent->model->DrawDepth != NULL)
7927                         ent->model->DrawDepth(ent);
7928         }
7929 }
7930
7931 static void R_DrawModelsDebug(void)
7932 {
7933         int i;
7934         entity_render_t *ent;
7935
7936         for (i = 0;i < r_refdef.scene.numentities;i++)
7937         {
7938                 if (!r_refdef.viewcache.entityvisible[i])
7939                         continue;
7940                 ent = r_refdef.scene.entities[i];
7941                 if (ent->model && ent->model->DrawDebug != NULL)
7942                         ent->model->DrawDebug(ent);
7943         }
7944 }
7945
7946 static void R_DrawModelsAddWaterPlanes(void)
7947 {
7948         int i;
7949         entity_render_t *ent;
7950
7951         for (i = 0;i < r_refdef.scene.numentities;i++)
7952         {
7953                 if (!r_refdef.viewcache.entityvisible[i])
7954                         continue;
7955                 ent = r_refdef.scene.entities[i];
7956                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7957                         ent->model->DrawAddWaterPlanes(ent);
7958         }
7959 }
7960
7961 static void R_View_SetFrustum(void)
7962 {
7963         int i;
7964         double slopex, slopey;
7965         vec3_t forward, left, up, origin;
7966
7967         // we can't trust r_refdef.view.forward and friends in reflected scenes
7968         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7969
7970 #if 0
7971         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7972         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7973         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7974         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7975         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7976         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7977         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7978         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7979         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7980         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7981         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7982         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7983 #endif
7984
7985 #if 0
7986         zNear = r_refdef.nearclip;
7987         nudge = 1.0 - 1.0 / (1<<23);
7988         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7989         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7990         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7991         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7992         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7993         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7994         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7995         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7996 #endif
7997
7998
7999
8000 #if 0
8001         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8002         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8003         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8004         r_refdef.view.frustum[0].dist = m[15] - m[12];
8005
8006         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8007         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8008         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8009         r_refdef.view.frustum[1].dist = m[15] + m[12];
8010
8011         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8012         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8013         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8014         r_refdef.view.frustum[2].dist = m[15] - m[13];
8015
8016         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8017         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8018         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8019         r_refdef.view.frustum[3].dist = m[15] + m[13];
8020
8021         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8022         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8023         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8024         r_refdef.view.frustum[4].dist = m[15] - m[14];
8025
8026         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8027         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8028         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8029         r_refdef.view.frustum[5].dist = m[15] + m[14];
8030 #endif
8031
8032         if (r_refdef.view.useperspective)
8033         {
8034                 slopex = 1.0 / r_refdef.view.frustum_x;
8035                 slopey = 1.0 / r_refdef.view.frustum_y;
8036                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8037                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8038                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8039                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8040                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8041
8042                 // Leaving those out was a mistake, those were in the old code, and they
8043                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8044                 // I couldn't reproduce it after adding those normalizations. --blub
8045                 VectorNormalize(r_refdef.view.frustum[0].normal);
8046                 VectorNormalize(r_refdef.view.frustum[1].normal);
8047                 VectorNormalize(r_refdef.view.frustum[2].normal);
8048                 VectorNormalize(r_refdef.view.frustum[3].normal);
8049
8050                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8051                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8052                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8053                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8054                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8055
8056                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8057                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8058                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8059                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8060                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8061         }
8062         else
8063         {
8064                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8065                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8066                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8067                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8068                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8069                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8070                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8071                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8072                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8073                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8074         }
8075         r_refdef.view.numfrustumplanes = 5;
8076
8077         if (r_refdef.view.useclipplane)
8078         {
8079                 r_refdef.view.numfrustumplanes = 6;
8080                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8081         }
8082
8083         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8084                 PlaneClassify(r_refdef.view.frustum + i);
8085
8086         // LordHavoc: note to all quake engine coders, Quake had a special case
8087         // for 90 degrees which assumed a square view (wrong), so I removed it,
8088         // Quake2 has it disabled as well.
8089
8090         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8091         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8092         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8093         //PlaneClassify(&frustum[0]);
8094
8095         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8096         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8097         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8098         //PlaneClassify(&frustum[1]);
8099
8100         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8101         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8102         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8103         //PlaneClassify(&frustum[2]);
8104
8105         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8106         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8107         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8108         //PlaneClassify(&frustum[3]);
8109
8110         // nearclip plane
8111         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8112         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8113         //PlaneClassify(&frustum[4]);
8114 }
8115
8116 void R_View_Update(void)
8117 {
8118         R_Main_ResizeViewCache();
8119         R_View_SetFrustum();
8120         R_View_WorldVisibility(r_refdef.view.useclipplane);
8121         R_View_UpdateEntityVisible();
8122         R_View_UpdateEntityLighting();
8123 }
8124
8125 void R_SetupView(qboolean allowwaterclippingplane)
8126 {
8127         const float *customclipplane = NULL;
8128         float plane[4];
8129         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8130         {
8131                 // LordHavoc: couldn't figure out how to make this approach the
8132                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8133                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8134                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8135                         dist = r_refdef.view.clipplane.dist;
8136                 plane[0] = r_refdef.view.clipplane.normal[0];
8137                 plane[1] = r_refdef.view.clipplane.normal[1];
8138                 plane[2] = r_refdef.view.clipplane.normal[2];
8139                 plane[3] = dist;
8140                 customclipplane = plane;
8141         }
8142
8143         if (!r_refdef.view.useperspective)
8144                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
8145         else if (vid.stencil && r_useinfinitefarclip.integer)
8146                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
8147         else
8148                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
8149         R_SetViewport(&r_refdef.view.viewport);
8150 }
8151
8152 void R_EntityMatrix(const matrix4x4_t *matrix)
8153 {
8154         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8155         {
8156                 gl_modelmatrixchanged = false;
8157                 gl_modelmatrix = *matrix;
8158                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8159                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8160                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8161                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8162                 CHECKGLERROR
8163                 switch(vid.renderpath)
8164                 {
8165                 case RENDERPATH_D3D9:
8166 #ifdef SUPPORTD3D
8167                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8168                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8169 #endif
8170                         break;
8171                 case RENDERPATH_D3D10:
8172                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8173                         break;
8174                 case RENDERPATH_D3D11:
8175                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8176                         break;
8177                 case RENDERPATH_GL20:
8178                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8179                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8180                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8181                         break;
8182                 case RENDERPATH_CGGL:
8183 #ifdef SUPPORTCG
8184                         CHECKCGERROR
8185                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8186                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8187                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8188 #endif
8189                         break;
8190                 case RENDERPATH_GL13:
8191                 case RENDERPATH_GL11:
8192                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8193                         break;
8194                 }
8195         }
8196 }
8197
8198 void R_ResetViewRendering2D(void)
8199 {
8200         r_viewport_t viewport;
8201         DrawQ_Finish();
8202
8203         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8204         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
8205         R_SetViewport(&viewport);
8206         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8207         GL_Color(1, 1, 1, 1);
8208         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8209         GL_BlendFunc(GL_ONE, GL_ZERO);
8210         GL_AlphaTest(false);
8211         GL_ScissorTest(false);
8212         GL_DepthMask(false);
8213         GL_DepthRange(0, 1);
8214         GL_DepthTest(false);
8215         GL_DepthFunc(GL_LEQUAL);
8216         R_EntityMatrix(&identitymatrix);
8217         R_Mesh_ResetTextureState();
8218         GL_PolygonOffset(0, 0);
8219         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8220         switch(vid.renderpath)
8221         {
8222         case RENDERPATH_GL11:
8223         case RENDERPATH_GL13:
8224         case RENDERPATH_GL20:
8225         case RENDERPATH_CGGL:
8226                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8227                 break;
8228         case RENDERPATH_D3D9:
8229         case RENDERPATH_D3D10:
8230         case RENDERPATH_D3D11:
8231                 break;
8232         }
8233         GL_CullFace(GL_NONE);
8234 }
8235
8236 void R_ResetViewRendering3D(void)
8237 {
8238         DrawQ_Finish();
8239
8240         R_SetupView(true);
8241         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8242         GL_Color(1, 1, 1, 1);
8243         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8244         GL_BlendFunc(GL_ONE, GL_ZERO);
8245         GL_AlphaTest(false);
8246         GL_ScissorTest(true);
8247         GL_DepthMask(true);
8248         GL_DepthRange(0, 1);
8249         GL_DepthTest(true);
8250         GL_DepthFunc(GL_LEQUAL);
8251         R_EntityMatrix(&identitymatrix);
8252         R_Mesh_ResetTextureState();
8253         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8254         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8255         switch(vid.renderpath)
8256         {
8257         case RENDERPATH_GL11:
8258         case RENDERPATH_GL13:
8259         case RENDERPATH_GL20:
8260         case RENDERPATH_CGGL:
8261                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8262                 break;
8263         case RENDERPATH_D3D9:
8264         case RENDERPATH_D3D10:
8265         case RENDERPATH_D3D11:
8266                 break;
8267         }
8268         GL_CullFace(r_refdef.view.cullface_back);
8269 }
8270
8271 /*
8272 ================
8273 R_RenderView_UpdateViewVectors
8274 ================
8275 */
8276 static void R_RenderView_UpdateViewVectors(void)
8277 {
8278         // break apart the view matrix into vectors for various purposes
8279         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8280         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8281         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8282         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8283         // make an inverted copy of the view matrix for tracking sprites
8284         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8285 }
8286
8287 void R_RenderScene(void);
8288 void R_RenderWaterPlanes(void);
8289
8290 static void R_Water_StartFrame(void)
8291 {
8292         int i;
8293         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8294         r_waterstate_waterplane_t *p;
8295
8296         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8297                 return;
8298
8299         switch(vid.renderpath)
8300         {
8301         case RENDERPATH_GL20:
8302         case RENDERPATH_CGGL:
8303         case RENDERPATH_D3D9:
8304         case RENDERPATH_D3D10:
8305         case RENDERPATH_D3D11:
8306                 break;
8307         case RENDERPATH_GL13:
8308         case RENDERPATH_GL11:
8309                 return;
8310         }
8311
8312         // set waterwidth and waterheight to the water resolution that will be
8313         // used (often less than the screen resolution for faster rendering)
8314         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8315         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8316
8317         // calculate desired texture sizes
8318         // can't use water if the card does not support the texture size
8319         if (!r_water.integer || r_showsurfaces.integer)
8320                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8321         else if (vid.support.arb_texture_non_power_of_two)
8322         {
8323                 texturewidth = waterwidth;
8324                 textureheight = waterheight;
8325                 camerawidth = waterwidth;
8326                 cameraheight = waterheight;
8327         }
8328         else
8329         {
8330                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8331                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8332                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8333                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8334         }
8335
8336         // allocate textures as needed
8337         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8338         {
8339                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8340                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8341                 {
8342                         if (p->texture_refraction)
8343                                 R_FreeTexture(p->texture_refraction);
8344                         p->texture_refraction = NULL;
8345                         if (p->texture_reflection)
8346                                 R_FreeTexture(p->texture_reflection);
8347                         p->texture_reflection = NULL;
8348                         if (p->texture_camera)
8349                                 R_FreeTexture(p->texture_camera);
8350                         p->texture_camera = NULL;
8351                 }
8352                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8353                 r_waterstate.texturewidth = texturewidth;
8354                 r_waterstate.textureheight = textureheight;
8355                 r_waterstate.camerawidth = camerawidth;
8356                 r_waterstate.cameraheight = cameraheight;
8357         }
8358
8359         if (r_waterstate.texturewidth)
8360         {
8361                 r_waterstate.enabled = true;
8362
8363                 // when doing a reduced render (HDR) we want to use a smaller area
8364                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8365                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8366
8367                 // set up variables that will be used in shader setup
8368                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8369                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8370                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8371                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8372         }
8373
8374         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8375         r_waterstate.numwaterplanes = 0;
8376 }
8377
8378 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8379 {
8380         int triangleindex, planeindex;
8381         const int *e;
8382         vec3_t vert[3];
8383         vec3_t normal;
8384         vec3_t center;
8385         mplane_t plane;
8386         int cam_ent;
8387         r_waterstate_waterplane_t *p;
8388         texture_t *t = R_GetCurrentTexture(surface->texture);
8389         cam_ent = t->camera_entity;
8390         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8391                 cam_ent = 0;
8392
8393         // just use the first triangle with a valid normal for any decisions
8394         VectorClear(normal);
8395         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8396         {
8397                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8398                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8399                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8400                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8401                 if (VectorLength2(normal) >= 0.001)
8402                         break;
8403         }
8404
8405         VectorCopy(normal, plane.normal);
8406         VectorNormalize(plane.normal);
8407         plane.dist = DotProduct(vert[0], plane.normal);
8408         PlaneClassify(&plane);
8409         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8410         {
8411                 // skip backfaces (except if nocullface is set)
8412                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8413                         return;
8414                 VectorNegate(plane.normal, plane.normal);
8415                 plane.dist *= -1;
8416                 PlaneClassify(&plane);
8417         }
8418
8419
8420         // find a matching plane if there is one
8421         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8422                 if(p->camera_entity == t->camera_entity)
8423                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8424                                 break;
8425         if (planeindex >= r_waterstate.maxwaterplanes)
8426                 return; // nothing we can do, out of planes
8427
8428         // if this triangle does not fit any known plane rendered this frame, add one
8429         if (planeindex >= r_waterstate.numwaterplanes)
8430         {
8431                 // store the new plane
8432                 r_waterstate.numwaterplanes++;
8433                 p->plane = plane;
8434                 // clear materialflags and pvs
8435                 p->materialflags = 0;
8436                 p->pvsvalid = false;
8437                 p->camera_entity = t->camera_entity;
8438         }
8439         // merge this surface's materialflags into the waterplane
8440         p->materialflags |= t->currentmaterialflags;
8441         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8442         {
8443                 // merge this surface's PVS into the waterplane
8444                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8445                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8446                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8447                 {
8448                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8449                         p->pvsvalid = true;
8450                 }
8451         }
8452 }
8453
8454 static void R_Water_ProcessPlanes(void)
8455 {
8456         r_refdef_view_t originalview;
8457         r_refdef_view_t myview;
8458         int planeindex;
8459         r_waterstate_waterplane_t *p;
8460         vec3_t visorigin;
8461
8462         originalview = r_refdef.view;
8463
8464         // make sure enough textures are allocated
8465         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8466         {
8467                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8468                 {
8469                         if (!p->texture_refraction)
8470                                 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);
8471                         if (!p->texture_refraction)
8472                                 goto error;
8473                 }
8474                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8475                 {
8476                         if (!p->texture_camera)
8477                                 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);
8478                         if (!p->texture_camera)
8479                                 goto error;
8480                 }
8481
8482                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8483                 {
8484                         if (!p->texture_reflection)
8485                                 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);
8486                         if (!p->texture_reflection)
8487                                 goto error;
8488                 }
8489         }
8490
8491         // render views
8492         r_refdef.view = originalview;
8493         r_refdef.view.showdebug = false;
8494         r_refdef.view.width = r_waterstate.waterwidth;
8495         r_refdef.view.height = r_waterstate.waterheight;
8496         r_refdef.view.useclipplane = true;
8497         myview = r_refdef.view;
8498         r_waterstate.renderingscene = true;
8499         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8500         {
8501                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8502                 {
8503                         r_refdef.view = myview;
8504                         // render reflected scene and copy into texture
8505                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8506                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8507                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8508                         r_refdef.view.clipplane = p->plane;
8509                         // reverse the cullface settings for this render
8510                         r_refdef.view.cullface_front = GL_FRONT;
8511                         r_refdef.view.cullface_back = GL_BACK;
8512                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8513                         {
8514                                 r_refdef.view.usecustompvs = true;
8515                                 if (p->pvsvalid)
8516                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8517                                 else
8518                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8519                         }
8520
8521                         R_ResetViewRendering3D();
8522                         R_ClearScreen(r_refdef.fogenabled);
8523                         R_View_Update();
8524                         R_RenderScene();
8525
8526                         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);
8527                 }
8528
8529                 // render the normal view scene and copy into texture
8530                 // (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)
8531                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8532                 {
8533                         r_waterstate.renderingrefraction = true;
8534                         r_refdef.view = myview;
8535
8536                         r_refdef.view.clipplane = p->plane;
8537                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8538                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8539
8540                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8541                         {
8542                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8543                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8544                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8545                                 R_RenderView_UpdateViewVectors();
8546                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8547                                 {
8548                                         r_refdef.view.usecustompvs = true;
8549                                         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);
8550                                 }
8551                         }
8552
8553                         PlaneClassify(&r_refdef.view.clipplane);
8554
8555                         R_ResetViewRendering3D();
8556                         R_ClearScreen(r_refdef.fogenabled);
8557                         R_View_Update();
8558                         R_RenderScene();
8559
8560                         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);
8561                         r_waterstate.renderingrefraction = false;
8562                 }
8563                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8564                 {
8565                         r_refdef.view = myview;
8566
8567                         r_refdef.view.clipplane = p->plane;
8568                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8569                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8570
8571                         r_refdef.view.width = r_waterstate.camerawidth;
8572                         r_refdef.view.height = r_waterstate.cameraheight;
8573                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8574                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8575
8576                         if(p->camera_entity)
8577                         {
8578                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8579                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8580                         }
8581
8582                         // reverse the cullface settings for this render
8583                         r_refdef.view.cullface_front = GL_FRONT;
8584                         r_refdef.view.cullface_back = GL_BACK;
8585                         // also reverse the view matrix
8586                         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
8587                         R_RenderView_UpdateViewVectors();
8588                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8589                         {
8590                                 r_refdef.view.usecustompvs = true;
8591                                 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);
8592                         }
8593                         
8594                         // camera needs no clipplane
8595                         r_refdef.view.useclipplane = false;
8596
8597                         PlaneClassify(&r_refdef.view.clipplane);
8598
8599                         R_ResetViewRendering3D();
8600                         R_ClearScreen(r_refdef.fogenabled);
8601                         R_View_Update();
8602                         R_RenderScene();
8603
8604                         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);
8605                         r_waterstate.renderingrefraction = false;
8606                 }
8607
8608         }
8609         r_waterstate.renderingscene = false;
8610         r_refdef.view = originalview;
8611         R_ResetViewRendering3D();
8612         R_ClearScreen(r_refdef.fogenabled);
8613         R_View_Update();
8614         return;
8615 error:
8616         r_refdef.view = originalview;
8617         r_waterstate.renderingscene = false;
8618         Cvar_SetValueQuick(&r_water, 0);
8619         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8620         return;
8621 }
8622
8623 void R_Bloom_StartFrame(void)
8624 {
8625         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8626
8627         switch(vid.renderpath)
8628         {
8629         case RENDERPATH_GL20:
8630         case RENDERPATH_CGGL:
8631         case RENDERPATH_D3D9:
8632         case RENDERPATH_D3D10:
8633         case RENDERPATH_D3D11:
8634                 break;
8635         case RENDERPATH_GL13:
8636         case RENDERPATH_GL11:
8637                 return;
8638         }
8639
8640         // set bloomwidth and bloomheight to the bloom resolution that will be
8641         // used (often less than the screen resolution for faster rendering)
8642         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8643         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8644         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8645         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8646         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8647
8648         // calculate desired texture sizes
8649         if (vid.support.arb_texture_non_power_of_two)
8650         {
8651                 screentexturewidth = r_refdef.view.width;
8652                 screentextureheight = r_refdef.view.height;
8653                 bloomtexturewidth = r_bloomstate.bloomwidth;
8654                 bloomtextureheight = r_bloomstate.bloomheight;
8655         }
8656         else
8657         {
8658                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8659                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8660                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8661                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8662         }
8663
8664         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))
8665         {
8666                 Cvar_SetValueQuick(&r_hdr, 0);
8667                 Cvar_SetValueQuick(&r_bloom, 0);
8668                 Cvar_SetValueQuick(&r_motionblur, 0);
8669                 Cvar_SetValueQuick(&r_damageblur, 0);
8670         }
8671
8672         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)))
8673                 screentexturewidth = screentextureheight = 0;
8674         if (!r_hdr.integer && !r_bloom.integer)
8675                 bloomtexturewidth = bloomtextureheight = 0;
8676
8677         // allocate textures as needed
8678         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8679         {
8680                 if (r_bloomstate.texture_screen)
8681                         R_FreeTexture(r_bloomstate.texture_screen);
8682                 r_bloomstate.texture_screen = NULL;
8683                 r_bloomstate.screentexturewidth = screentexturewidth;
8684                 r_bloomstate.screentextureheight = screentextureheight;
8685                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8686                         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);
8687         }
8688         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8689         {
8690                 if (r_bloomstate.texture_bloom)
8691                         R_FreeTexture(r_bloomstate.texture_bloom);
8692                 r_bloomstate.texture_bloom = NULL;
8693                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8694                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8695                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8696                         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);
8697         }
8698
8699         // when doing a reduced render (HDR) we want to use a smaller area
8700         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8701         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8702         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8703         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8704         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8705
8706         // set up a texcoord array for the full resolution screen image
8707         // (we have to keep this around to copy back during final render)
8708         r_bloomstate.screentexcoord2f[0] = 0;
8709         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8710         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8711         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8712         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8713         r_bloomstate.screentexcoord2f[5] = 0;
8714         r_bloomstate.screentexcoord2f[6] = 0;
8715         r_bloomstate.screentexcoord2f[7] = 0;
8716
8717         // set up a texcoord array for the reduced resolution bloom image
8718         // (which will be additive blended over the screen image)
8719         r_bloomstate.bloomtexcoord2f[0] = 0;
8720         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8721         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8722         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8723         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8724         r_bloomstate.bloomtexcoord2f[5] = 0;
8725         r_bloomstate.bloomtexcoord2f[6] = 0;
8726         r_bloomstate.bloomtexcoord2f[7] = 0;
8727
8728         switch(vid.renderpath)
8729         {
8730         case RENDERPATH_GL11:
8731         case RENDERPATH_GL13:
8732         case RENDERPATH_GL20:
8733         case RENDERPATH_CGGL:
8734                 break;
8735         case RENDERPATH_D3D9:
8736         case RENDERPATH_D3D10:
8737         case RENDERPATH_D3D11:
8738                 {
8739                         int i;
8740                         for (i = 0;i < 4;i++)
8741                         {
8742                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8743                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8744                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8745                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8746                         }
8747                 }
8748                 break;
8749         }
8750
8751         if (r_hdr.integer || r_bloom.integer)
8752         {
8753                 r_bloomstate.enabled = true;
8754                 r_bloomstate.hdr = r_hdr.integer != 0;
8755         }
8756
8757         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);
8758 }
8759
8760 void R_Bloom_CopyBloomTexture(float colorscale)
8761 {
8762         r_refdef.stats.bloom++;
8763
8764         // scale down screen texture to the bloom texture size
8765         CHECKGLERROR
8766         R_SetViewport(&r_bloomstate.viewport);
8767         GL_BlendFunc(GL_ONE, GL_ZERO);
8768         GL_Color(colorscale, colorscale, colorscale, 1);
8769         // 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...
8770         switch(vid.renderpath)
8771         {
8772         case RENDERPATH_GL11:
8773         case RENDERPATH_GL13:
8774         case RENDERPATH_GL20:
8775         case RENDERPATH_CGGL:
8776                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8777                 break;
8778         case RENDERPATH_D3D9:
8779         case RENDERPATH_D3D10:
8780         case RENDERPATH_D3D11:
8781                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8782                 break;
8783         }
8784         // TODO: do boxfilter scale-down in shader?
8785         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8786         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8787         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8788
8789         // we now have a bloom image in the framebuffer
8790         // copy it into the bloom image texture for later processing
8791         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);
8792         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8793 }
8794
8795 void R_Bloom_CopyHDRTexture(void)
8796 {
8797         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);
8798         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8799 }
8800
8801 void R_Bloom_MakeTexture(void)
8802 {
8803         int x, range, dir;
8804         float xoffset, yoffset, r, brighten;
8805
8806         r_refdef.stats.bloom++;
8807
8808         R_ResetViewRendering2D();
8809
8810         // we have a bloom image in the framebuffer
8811         CHECKGLERROR
8812         R_SetViewport(&r_bloomstate.viewport);
8813
8814         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8815         {
8816                 x *= 2;
8817                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8818                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8819                 GL_Color(r,r,r,1);
8820                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8821                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8822                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8823                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8824
8825                 // copy the vertically blurred bloom view to a texture
8826                 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);
8827                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8828         }
8829
8830         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8831         brighten = r_bloom_brighten.value;
8832         if (r_hdr.integer)
8833                 brighten *= r_hdr_range.value;
8834         brighten = sqrt(brighten);
8835         if(range >= 1)
8836                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8837         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8838
8839         for (dir = 0;dir < 2;dir++)
8840         {
8841                 // blend on at multiple vertical offsets to achieve a vertical blur
8842                 // TODO: do offset blends using GLSL
8843                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8844                 GL_BlendFunc(GL_ONE, GL_ZERO);
8845                 for (x = -range;x <= range;x++)
8846                 {
8847                         if (!dir){xoffset = 0;yoffset = x;}
8848                         else {xoffset = x;yoffset = 0;}
8849                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8850                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8851                         // compute a texcoord array with the specified x and y offset
8852                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8853                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8854                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8855                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8856                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8857                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8858                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8859                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8860                         // this r value looks like a 'dot' particle, fading sharply to
8861                         // black at the edges
8862                         // (probably not realistic but looks good enough)
8863                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8864                         //r = brighten/(range*2+1);
8865                         r = brighten / (range * 2 + 1);
8866                         if(range >= 1)
8867                                 r *= (1 - x*x/(float)(range*range));
8868                         GL_Color(r, r, r, 1);
8869                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8870                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8871                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8872                         GL_BlendFunc(GL_ONE, GL_ONE);
8873                 }
8874
8875                 // copy the vertically blurred bloom view to a texture
8876                 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);
8877                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8878         }
8879 }
8880
8881 void R_HDR_RenderBloomTexture(void)
8882 {
8883         int oldwidth, oldheight;
8884         float oldcolorscale;
8885
8886         oldcolorscale = r_refdef.view.colorscale;
8887         oldwidth = r_refdef.view.width;
8888         oldheight = r_refdef.view.height;
8889         r_refdef.view.width = r_bloomstate.bloomwidth;
8890         r_refdef.view.height = r_bloomstate.bloomheight;
8891
8892         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8893         // TODO: add exposure compensation features
8894         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8895
8896         r_refdef.view.showdebug = false;
8897         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8898
8899         R_ResetViewRendering3D();
8900
8901         R_ClearScreen(r_refdef.fogenabled);
8902         if (r_timereport_active)
8903                 R_TimeReport("HDRclear");
8904
8905         R_View_Update();
8906         if (r_timereport_active)
8907                 R_TimeReport("visibility");
8908
8909         // only do secondary renders with HDR if r_hdr is 2 or higher
8910         r_waterstate.numwaterplanes = 0;
8911         if (r_waterstate.enabled && r_hdr.integer >= 2)
8912                 R_RenderWaterPlanes();
8913
8914         r_refdef.view.showdebug = true;
8915         R_RenderScene();
8916         r_waterstate.numwaterplanes = 0;
8917
8918         R_ResetViewRendering2D();
8919
8920         R_Bloom_CopyHDRTexture();
8921         R_Bloom_MakeTexture();
8922
8923         // restore the view settings
8924         r_refdef.view.width = oldwidth;
8925         r_refdef.view.height = oldheight;
8926         r_refdef.view.colorscale = oldcolorscale;
8927
8928         R_ResetViewRendering3D();
8929
8930         R_ClearScreen(r_refdef.fogenabled);
8931         if (r_timereport_active)
8932                 R_TimeReport("viewclear");
8933 }
8934
8935 static void R_BlendView(void)
8936 {
8937         unsigned int permutation;
8938         float uservecs[4][4];
8939
8940         switch (vid.renderpath)
8941         {
8942         case RENDERPATH_GL20:
8943         case RENDERPATH_CGGL:
8944         case RENDERPATH_D3D9:
8945         case RENDERPATH_D3D10:
8946         case RENDERPATH_D3D11:
8947                 permutation =
8948                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8949                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8950                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8951                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8952                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8953
8954                 if (r_bloomstate.texture_screen)
8955                 {
8956                         // make sure the buffer is available
8957                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8958
8959                         R_ResetViewRendering2D();
8960
8961                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8962                         {
8963                                 // declare variables
8964                                 float speed;
8965                                 static float avgspeed;
8966
8967                                 speed = VectorLength(cl.movement_velocity);
8968
8969                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8970                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8971
8972                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8973                                 speed = bound(0, speed, 1);
8974                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8975
8976                                 // calculate values into a standard alpha
8977                                 cl.motionbluralpha = 1 - exp(-
8978                                                 (
8979                                                  (r_motionblur.value * speed / 80)
8980                                                  +
8981                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8982                                                 )
8983                                                 /
8984                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8985                                            );
8986
8987                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8988                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8989                                 // apply the blur
8990                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8991                                 {
8992                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8993                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8994                                         switch(vid.renderpath)
8995                                         {
8996                                         case RENDERPATH_GL11:
8997                                         case RENDERPATH_GL13:
8998                                         case RENDERPATH_GL20:
8999                                         case RENDERPATH_CGGL:
9000                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9001                                                 break;
9002                                         case RENDERPATH_D3D9:
9003                                         case RENDERPATH_D3D10:
9004                                         case RENDERPATH_D3D11:
9005                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9006                                                 break;
9007                                         }
9008                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9009                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9010                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9011                                 }
9012                         }
9013
9014                         // copy view into the screen texture
9015                         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);
9016                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9017                 }
9018                 else if (!r_bloomstate.texture_bloom)
9019                 {
9020                         // we may still have to do view tint...
9021                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9022                         {
9023                                 // apply a color tint to the whole view
9024                                 R_ResetViewRendering2D();
9025                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9026                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9027                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9028                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9029                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9030                         }
9031                         break; // no screen processing, no bloom, skip it
9032                 }
9033
9034                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9035                 {
9036                         // render simple bloom effect
9037                         // copy the screen and shrink it and darken it for the bloom process
9038                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9039                         // make the bloom texture
9040                         R_Bloom_MakeTexture();
9041                 }
9042
9043 #if _MSC_VER >= 1400
9044 #define sscanf sscanf_s
9045 #endif
9046                 memset(uservecs, 0, sizeof(uservecs));
9047                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9048                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9049                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9050                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9051
9052                 R_ResetViewRendering2D();
9053                 GL_Color(1, 1, 1, 1);
9054                 GL_BlendFunc(GL_ONE, GL_ZERO);
9055
9056                 switch(vid.renderpath)
9057                 {
9058                 case RENDERPATH_GL20:
9059                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9060                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9061                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9062                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9063                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9064                         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]);
9065                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9066                         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]);
9067                         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]);
9068                         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]);
9069                         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]);
9070                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9071                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9072                         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);
9073                         break;
9074                 case RENDERPATH_CGGL:
9075 #ifdef SUPPORTCG
9076                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9077                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9078                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9079                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9080                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9081                         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
9082                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9083                         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
9084                         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
9085                         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
9086                         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
9087                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9088                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9089                         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);
9090 #endif
9091                         break;
9092                 case RENDERPATH_D3D9:
9093 #ifdef SUPPORTD3D
9094                         // 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...
9095                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9096                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9097                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9098                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9099                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9100                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9101                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9102                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9103                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9104                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9105                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9106                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9107                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9108                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9109 #endif
9110                         break;
9111                 case RENDERPATH_D3D10:
9112                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9113                         break;
9114                 case RENDERPATH_D3D11:
9115                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9116                         break;
9117                 default:
9118                         break;
9119                 }
9120                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9121                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9122                 break;
9123         case RENDERPATH_GL13:
9124         case RENDERPATH_GL11:
9125                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9126                 {
9127                         // apply a color tint to the whole view
9128                         R_ResetViewRendering2D();
9129                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9130                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9131                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9132                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9133                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9134                 }
9135                 break;
9136         }
9137 }
9138
9139 matrix4x4_t r_waterscrollmatrix;
9140
9141 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9142 {
9143         if (r_refdef.fog_density)
9144         {
9145                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9146                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9147                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9148
9149                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9150                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9151                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9152                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9153
9154                 {
9155                         vec3_t fogvec;
9156                         VectorCopy(r_refdef.fogcolor, fogvec);
9157                         //   color.rgb *= ContrastBoost * SceneBrightness;
9158                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9159                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9160                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9161                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9162                 }
9163         }
9164 }
9165
9166 void R_UpdateVariables(void)
9167 {
9168         R_Textures_Frame();
9169
9170         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9171
9172         r_refdef.farclip = r_farclip_base.value;
9173         if (r_refdef.scene.worldmodel)
9174                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9175         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9176
9177         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9178                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9179         r_refdef.polygonfactor = 0;
9180         r_refdef.polygonoffset = 0;
9181         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9182         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9183
9184         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9185         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9186         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9187         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9188         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9189         if (r_showsurfaces.integer)
9190         {
9191                 r_refdef.scene.rtworld = false;
9192                 r_refdef.scene.rtworldshadows = false;
9193                 r_refdef.scene.rtdlight = false;
9194                 r_refdef.scene.rtdlightshadows = false;
9195                 r_refdef.lightmapintensity = 0;
9196         }
9197
9198         if (gamemode == GAME_NEHAHRA)
9199         {
9200                 if (gl_fogenable.integer)
9201                 {
9202                         r_refdef.oldgl_fogenable = true;
9203                         r_refdef.fog_density = gl_fogdensity.value;
9204                         r_refdef.fog_red = gl_fogred.value;
9205                         r_refdef.fog_green = gl_foggreen.value;
9206                         r_refdef.fog_blue = gl_fogblue.value;
9207                         r_refdef.fog_alpha = 1;
9208                         r_refdef.fog_start = 0;
9209                         r_refdef.fog_end = gl_skyclip.value;
9210                         r_refdef.fog_height = 1<<30;
9211                         r_refdef.fog_fadedepth = 128;
9212                 }
9213                 else if (r_refdef.oldgl_fogenable)
9214                 {
9215                         r_refdef.oldgl_fogenable = false;
9216                         r_refdef.fog_density = 0;
9217                         r_refdef.fog_red = 0;
9218                         r_refdef.fog_green = 0;
9219                         r_refdef.fog_blue = 0;
9220                         r_refdef.fog_alpha = 0;
9221                         r_refdef.fog_start = 0;
9222                         r_refdef.fog_end = 0;
9223                         r_refdef.fog_height = 1<<30;
9224                         r_refdef.fog_fadedepth = 128;
9225                 }
9226         }
9227
9228         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9229         r_refdef.fog_start = max(0, r_refdef.fog_start);
9230         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9231
9232         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9233
9234         if (r_refdef.fog_density && r_drawfog.integer)
9235         {
9236                 r_refdef.fogenabled = true;
9237                 // this is the point where the fog reaches 0.9986 alpha, which we
9238                 // consider a good enough cutoff point for the texture
9239                 // (0.9986 * 256 == 255.6)
9240                 if (r_fog_exp2.integer)
9241                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9242                 else
9243                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9244                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9245                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9246                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9247                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9248                         R_BuildFogHeightTexture();
9249                 // fog color was already set
9250                 // update the fog texture
9251                 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)
9252                         R_BuildFogTexture();
9253                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9254                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9255         }
9256         else
9257                 r_refdef.fogenabled = false;
9258
9259         switch(vid.renderpath)
9260         {
9261         case RENDERPATH_GL20:
9262         case RENDERPATH_CGGL:
9263         case RENDERPATH_D3D9:
9264         case RENDERPATH_D3D10:
9265         case RENDERPATH_D3D11:
9266                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9267                 {
9268                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9269                         {
9270                                 // build GLSL gamma texture
9271 #define RAMPWIDTH 256
9272                                 unsigned short ramp[RAMPWIDTH * 3];
9273                                 unsigned char rampbgr[RAMPWIDTH][4];
9274                                 int i;
9275
9276                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9277
9278                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9279                                 for(i = 0; i < RAMPWIDTH; ++i)
9280                                 {
9281                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9282                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9283                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9284                                         rampbgr[i][3] = 0;
9285                                 }
9286                                 if (r_texture_gammaramps)
9287                                 {
9288                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9289                                 }
9290                                 else
9291                                 {
9292                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9293                                 }
9294                         }
9295                 }
9296                 else
9297                 {
9298                         // remove GLSL gamma texture
9299                 }
9300                 break;
9301         case RENDERPATH_GL13:
9302         case RENDERPATH_GL11:
9303                 break;
9304         }
9305 }
9306
9307 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9308 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9309 /*
9310 ================
9311 R_SelectScene
9312 ================
9313 */
9314 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9315         if( scenetype != r_currentscenetype ) {
9316                 // store the old scenetype
9317                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9318                 r_currentscenetype = scenetype;
9319                 // move in the new scene
9320                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9321         }
9322 }
9323
9324 /*
9325 ================
9326 R_GetScenePointer
9327 ================
9328 */
9329 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9330 {
9331         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9332         if( scenetype == r_currentscenetype ) {
9333                 return &r_refdef.scene;
9334         } else {
9335                 return &r_scenes_store[ scenetype ];
9336         }
9337 }
9338
9339 /*
9340 ================
9341 R_RenderView
9342 ================
9343 */
9344 void R_RenderView(void)
9345 {
9346         if (r_timereport_active)
9347                 R_TimeReport("start");
9348         r_textureframe++; // used only by R_GetCurrentTexture
9349         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9350
9351         if (!r_drawentities.integer)
9352                 r_refdef.scene.numentities = 0;
9353
9354         R_AnimCache_ClearCache();
9355         R_FrameData_NewFrame();
9356
9357         if (r_refdef.view.isoverlay)
9358         {
9359                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9360                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9361                 R_TimeReport("depthclear");
9362
9363                 r_refdef.view.showdebug = false;
9364
9365                 r_waterstate.enabled = false;
9366                 r_waterstate.numwaterplanes = 0;
9367
9368                 R_RenderScene();
9369
9370                 CHECKGLERROR
9371                 return;
9372         }
9373
9374         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9375                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9376
9377         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9378
9379         R_RenderView_UpdateViewVectors();
9380
9381         R_Shadow_UpdateWorldLightSelection();
9382
9383         R_Bloom_StartFrame();
9384         R_Water_StartFrame();
9385
9386         CHECKGLERROR
9387         if (r_timereport_active)
9388                 R_TimeReport("viewsetup");
9389
9390         R_ResetViewRendering3D();
9391
9392         if (r_refdef.view.clear || r_refdef.fogenabled)
9393         {
9394                 R_ClearScreen(r_refdef.fogenabled);
9395                 if (r_timereport_active)
9396                         R_TimeReport("viewclear");
9397         }
9398         r_refdef.view.clear = true;
9399
9400         // this produces a bloom texture to be used in R_BlendView() later
9401         if (r_hdr.integer && r_bloomstate.bloomwidth)
9402         {
9403                 R_HDR_RenderBloomTexture();
9404                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9405                 r_textureframe++; // used only by R_GetCurrentTexture
9406         }
9407
9408         r_refdef.view.showdebug = true;
9409
9410         R_View_Update();
9411         if (r_timereport_active)
9412                 R_TimeReport("visibility");
9413
9414         r_waterstate.numwaterplanes = 0;
9415         if (r_waterstate.enabled)
9416                 R_RenderWaterPlanes();
9417
9418         R_RenderScene();
9419         r_waterstate.numwaterplanes = 0;
9420
9421         R_BlendView();
9422         if (r_timereport_active)
9423                 R_TimeReport("blendview");
9424
9425         GL_Scissor(0, 0, vid.width, vid.height);
9426         GL_ScissorTest(false);
9427         CHECKGLERROR
9428 }
9429
9430 void R_RenderWaterPlanes(void)
9431 {
9432         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9433         {
9434                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9435                 if (r_timereport_active)
9436                         R_TimeReport("waterworld");
9437         }
9438
9439         // don't let sound skip if going slow
9440         if (r_refdef.scene.extraupdate)
9441                 S_ExtraUpdate ();
9442
9443         R_DrawModelsAddWaterPlanes();
9444         if (r_timereport_active)
9445                 R_TimeReport("watermodels");
9446
9447         if (r_waterstate.numwaterplanes)
9448         {
9449                 R_Water_ProcessPlanes();
9450                 if (r_timereport_active)
9451                         R_TimeReport("waterscenes");
9452         }
9453 }
9454
9455 extern void R_DrawLightningBeams (void);
9456 extern void VM_CL_AddPolygonsToMeshQueue (void);
9457 extern void R_DrawPortals (void);
9458 extern cvar_t cl_locs_show;
9459 static void R_DrawLocs(void);
9460 static void R_DrawEntityBBoxes(void);
9461 static void R_DrawModelDecals(void);
9462 extern void R_DrawModelShadows(void);
9463 extern void R_DrawModelShadowMaps(void);
9464 extern cvar_t cl_decals_newsystem;
9465 extern qboolean r_shadow_usingdeferredprepass;
9466 void R_RenderScene(void)
9467 {
9468         qboolean shadowmapping = false;
9469
9470         if (r_timereport_active)
9471                 R_TimeReport("beginscene");
9472
9473         r_refdef.stats.renders++;
9474
9475         R_UpdateFogColor();
9476
9477         // don't let sound skip if going slow
9478         if (r_refdef.scene.extraupdate)
9479                 S_ExtraUpdate ();
9480
9481         R_MeshQueue_BeginScene();
9482
9483         R_SkyStartFrame();
9484
9485         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);
9486
9487         if (r_timereport_active)
9488                 R_TimeReport("skystartframe");
9489
9490         if (cl.csqc_vidvars.drawworld)
9491         {
9492                 // don't let sound skip if going slow
9493                 if (r_refdef.scene.extraupdate)
9494                         S_ExtraUpdate ();
9495
9496                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9497                 {
9498                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9499                         if (r_timereport_active)
9500                                 R_TimeReport("worldsky");
9501                 }
9502
9503                 if (R_DrawBrushModelsSky() && r_timereport_active)
9504                         R_TimeReport("bmodelsky");
9505
9506                 if (skyrendermasked && skyrenderlater)
9507                 {
9508                         // we have to force off the water clipping plane while rendering sky
9509                         R_SetupView(false);
9510                         R_Sky();
9511                         R_SetupView(true);
9512                         if (r_timereport_active)
9513                                 R_TimeReport("sky");
9514                 }
9515         }
9516
9517         R_AnimCache_CacheVisibleEntities();
9518         if (r_timereport_active)
9519                 R_TimeReport("animation");
9520
9521         R_Shadow_PrepareLights();
9522         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9523                 R_Shadow_PrepareModelShadows();
9524         if (r_timereport_active)
9525                 R_TimeReport("preparelights");
9526
9527         if (R_Shadow_ShadowMappingEnabled())
9528                 shadowmapping = true;
9529
9530         if (r_shadow_usingdeferredprepass)
9531                 R_Shadow_DrawPrepass();
9532
9533         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9534         {
9535                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9536                 if (r_timereport_active)
9537                         R_TimeReport("worlddepth");
9538         }
9539         if (r_depthfirst.integer >= 2)
9540         {
9541                 R_DrawModelsDepth();
9542                 if (r_timereport_active)
9543                         R_TimeReport("modeldepth");
9544         }
9545
9546         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9547         {
9548                 R_DrawModelShadowMaps();
9549                 R_ResetViewRendering3D();
9550                 // don't let sound skip if going slow
9551                 if (r_refdef.scene.extraupdate)
9552                         S_ExtraUpdate ();
9553         }
9554
9555         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9556         {
9557                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9558                 if (r_timereport_active)
9559                         R_TimeReport("world");
9560         }
9561
9562         // don't let sound skip if going slow
9563         if (r_refdef.scene.extraupdate)
9564                 S_ExtraUpdate ();
9565
9566         R_DrawModels();
9567         if (r_timereport_active)
9568                 R_TimeReport("models");
9569
9570         // don't let sound skip if going slow
9571         if (r_refdef.scene.extraupdate)
9572                 S_ExtraUpdate ();
9573
9574         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9575         {
9576                 R_DrawModelShadows();
9577                 R_ResetViewRendering3D();
9578                 // don't let sound skip if going slow
9579                 if (r_refdef.scene.extraupdate)
9580                         S_ExtraUpdate ();
9581         }
9582
9583         if (!r_shadow_usingdeferredprepass)
9584         {
9585                 R_Shadow_DrawLights();
9586                 if (r_timereport_active)
9587                         R_TimeReport("rtlights");
9588         }
9589
9590         // don't let sound skip if going slow
9591         if (r_refdef.scene.extraupdate)
9592                 S_ExtraUpdate ();
9593
9594         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9595         {
9596                 R_DrawModelShadows();
9597                 R_ResetViewRendering3D();
9598                 // don't let sound skip if going slow
9599                 if (r_refdef.scene.extraupdate)
9600                         S_ExtraUpdate ();
9601         }
9602
9603         if (cl.csqc_vidvars.drawworld)
9604         {
9605                 if (cl_decals_newsystem.integer)
9606                 {
9607                         R_DrawModelDecals();
9608                         if (r_timereport_active)
9609                                 R_TimeReport("modeldecals");
9610                 }
9611                 else
9612                 {
9613                         R_DrawDecals();
9614                         if (r_timereport_active)
9615                                 R_TimeReport("decals");
9616                 }
9617
9618                 R_DrawParticles();
9619                 if (r_timereport_active)
9620                         R_TimeReport("particles");
9621
9622                 R_DrawExplosions();
9623                 if (r_timereport_active)
9624                         R_TimeReport("explosions");
9625
9626                 R_DrawLightningBeams();
9627                 if (r_timereport_active)
9628                         R_TimeReport("lightning");
9629         }
9630
9631         VM_CL_AddPolygonsToMeshQueue();
9632
9633         if (r_refdef.view.showdebug)
9634         {
9635                 if (cl_locs_show.integer)
9636                 {
9637                         R_DrawLocs();
9638                         if (r_timereport_active)
9639                                 R_TimeReport("showlocs");
9640                 }
9641
9642                 if (r_drawportals.integer)
9643                 {
9644                         R_DrawPortals();
9645                         if (r_timereport_active)
9646                                 R_TimeReport("portals");
9647                 }
9648
9649                 if (r_showbboxes.value > 0)
9650                 {
9651                         R_DrawEntityBBoxes();
9652                         if (r_timereport_active)
9653                                 R_TimeReport("bboxes");
9654                 }
9655         }
9656
9657         R_MeshQueue_RenderTransparent();
9658         if (r_timereport_active)
9659                 R_TimeReport("drawtrans");
9660
9661         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))
9662         {
9663                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9664                 if (r_timereport_active)
9665                         R_TimeReport("worlddebug");
9666                 R_DrawModelsDebug();
9667                 if (r_timereport_active)
9668                         R_TimeReport("modeldebug");
9669         }
9670
9671         if (cl.csqc_vidvars.drawworld)
9672         {
9673                 R_Shadow_DrawCoronas();
9674                 if (r_timereport_active)
9675                         R_TimeReport("coronas");
9676         }
9677
9678         // don't let sound skip if going slow
9679         if (r_refdef.scene.extraupdate)
9680                 S_ExtraUpdate ();
9681
9682         R_ResetViewRendering2D();
9683 }
9684
9685 static const unsigned short bboxelements[36] =
9686 {
9687         5, 1, 3, 5, 3, 7,
9688         6, 2, 0, 6, 0, 4,
9689         7, 3, 2, 7, 2, 6,
9690         4, 0, 1, 4, 1, 5,
9691         4, 5, 7, 4, 7, 6,
9692         1, 0, 2, 1, 2, 3,
9693 };
9694
9695 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9696 {
9697         int i;
9698         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9699
9700         RSurf_ActiveWorldEntity();
9701
9702         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9703         GL_DepthMask(false);
9704         GL_DepthRange(0, 1);
9705         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9706         R_Mesh_ResetTextureState();
9707
9708         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9709         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9710         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9711         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9712         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9713         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9714         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9715         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9716         R_FillColors(color4f, 8, cr, cg, cb, ca);
9717         if (r_refdef.fogenabled)
9718         {
9719                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9720                 {
9721                         f1 = RSurf_FogVertex(v);
9722                         f2 = 1 - f1;
9723                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9724                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9725                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9726                 }
9727         }
9728         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9729         R_Mesh_ResetTextureState();
9730         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9731         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9732 }
9733
9734 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9735 {
9736         int i;
9737         float color[4];
9738         prvm_edict_t *edict;
9739         prvm_prog_t *prog_save = prog;
9740
9741         // this function draws bounding boxes of server entities
9742         if (!sv.active)
9743                 return;
9744
9745         GL_CullFace(GL_NONE);
9746         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9747
9748         prog = 0;
9749         SV_VM_Begin();
9750         for (i = 0;i < numsurfaces;i++)
9751         {
9752                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9753                 switch ((int)edict->fields.server->solid)
9754                 {
9755                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9756                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9757                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9758                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9759                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9760                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9761                 }
9762                 color[3] *= r_showbboxes.value;
9763                 color[3] = bound(0, color[3], 1);
9764                 GL_DepthTest(!r_showdisabledepthtest.integer);
9765                 GL_CullFace(r_refdef.view.cullface_front);
9766                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9767         }
9768         SV_VM_End();
9769         prog = prog_save;
9770 }
9771
9772 static void R_DrawEntityBBoxes(void)
9773 {
9774         int i;
9775         prvm_edict_t *edict;
9776         vec3_t center;
9777         prvm_prog_t *prog_save = prog;
9778
9779         // this function draws bounding boxes of server entities
9780         if (!sv.active)
9781                 return;
9782
9783         prog = 0;
9784         SV_VM_Begin();
9785         for (i = 0;i < prog->num_edicts;i++)
9786         {
9787                 edict = PRVM_EDICT_NUM(i);
9788                 if (edict->priv.server->free)
9789                         continue;
9790                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9791                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9792                         continue;
9793                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9794                         continue;
9795                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9796                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9797         }
9798         SV_VM_End();
9799         prog = prog_save;
9800 }
9801
9802 static const int nomodelelement3i[24] =
9803 {
9804         5, 2, 0,
9805         5, 1, 2,
9806         5, 0, 3,
9807         5, 3, 1,
9808         0, 2, 4,
9809         2, 1, 4,
9810         3, 0, 4,
9811         1, 3, 4
9812 };
9813
9814 static const unsigned short nomodelelement3s[24] =
9815 {
9816         5, 2, 0,
9817         5, 1, 2,
9818         5, 0, 3,
9819         5, 3, 1,
9820         0, 2, 4,
9821         2, 1, 4,
9822         3, 0, 4,
9823         1, 3, 4
9824 };
9825
9826 static const float nomodelvertex3f[6*3] =
9827 {
9828         -16,   0,   0,
9829          16,   0,   0,
9830           0, -16,   0,
9831           0,  16,   0,
9832           0,   0, -16,
9833           0,   0,  16
9834 };
9835
9836 static const float nomodelcolor4f[6*4] =
9837 {
9838         0.0f, 0.0f, 0.5f, 1.0f,
9839         0.0f, 0.0f, 0.5f, 1.0f,
9840         0.0f, 0.5f, 0.0f, 1.0f,
9841         0.0f, 0.5f, 0.0f, 1.0f,
9842         0.5f, 0.0f, 0.0f, 1.0f,
9843         0.5f, 0.0f, 0.0f, 1.0f
9844 };
9845
9846 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9847 {
9848         int i;
9849         float f1, f2, *c;
9850         float color4f[6*4];
9851
9852         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);
9853
9854         // this is only called once per entity so numsurfaces is always 1, and
9855         // surfacelist is always {0}, so this code does not handle batches
9856
9857         if (rsurface.ent_flags & RENDER_ADDITIVE)
9858         {
9859                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9860                 GL_DepthMask(false);
9861         }
9862         else if (rsurface.colormod[3] < 1)
9863         {
9864                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9865                 GL_DepthMask(false);
9866         }
9867         else
9868         {
9869                 GL_BlendFunc(GL_ONE, GL_ZERO);
9870                 GL_DepthMask(true);
9871         }
9872         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9873         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9874         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9875         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9876         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9877         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9878         for (i = 0, c = color4f;i < 6;i++, c += 4)
9879         {
9880                 c[0] *= rsurface.colormod[0];
9881                 c[1] *= rsurface.colormod[1];
9882                 c[2] *= rsurface.colormod[2];
9883                 c[3] *= rsurface.colormod[3];
9884         }
9885         if (r_refdef.fogenabled)
9886         {
9887                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9888                 {
9889                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9890                         f2 = 1 - f1;
9891                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9892                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9893                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9894                 }
9895         }
9896         R_Mesh_ResetTextureState();
9897         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9898         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9899 }
9900
9901 void R_DrawNoModel(entity_render_t *ent)
9902 {
9903         vec3_t org;
9904         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9905         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9906                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9907         else
9908                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9909 }
9910
9911 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9912 {
9913         vec3_t right1, right2, diff, normal;
9914
9915         VectorSubtract (org2, org1, normal);
9916
9917         // calculate 'right' vector for start
9918         VectorSubtract (r_refdef.view.origin, org1, diff);
9919         CrossProduct (normal, diff, right1);
9920         VectorNormalize (right1);
9921
9922         // calculate 'right' vector for end
9923         VectorSubtract (r_refdef.view.origin, org2, diff);
9924         CrossProduct (normal, diff, right2);
9925         VectorNormalize (right2);
9926
9927         vert[ 0] = org1[0] + width * right1[0];
9928         vert[ 1] = org1[1] + width * right1[1];
9929         vert[ 2] = org1[2] + width * right1[2];
9930         vert[ 3] = org1[0] - width * right1[0];
9931         vert[ 4] = org1[1] - width * right1[1];
9932         vert[ 5] = org1[2] - width * right1[2];
9933         vert[ 6] = org2[0] - width * right2[0];
9934         vert[ 7] = org2[1] - width * right2[1];
9935         vert[ 8] = org2[2] - width * right2[2];
9936         vert[ 9] = org2[0] + width * right2[0];
9937         vert[10] = org2[1] + width * right2[1];
9938         vert[11] = org2[2] + width * right2[2];
9939 }
9940
9941 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)
9942 {
9943         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9944         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9945         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9946         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9947         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9948         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9949         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9950         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9951         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9952         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9953         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9954         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9955 }
9956
9957 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9958 {
9959         int i;
9960         float *vertex3f;
9961         float v[3];
9962         VectorSet(v, x, y, z);
9963         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9964                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9965                         break;
9966         if (i == mesh->numvertices)
9967         {
9968                 if (mesh->numvertices < mesh->maxvertices)
9969                 {
9970                         VectorCopy(v, vertex3f);
9971                         mesh->numvertices++;
9972                 }
9973                 return mesh->numvertices;
9974         }
9975         else
9976                 return i;
9977 }
9978
9979 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9980 {
9981         int i;
9982         int *e, element[3];
9983         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9984         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9985         e = mesh->element3i + mesh->numtriangles * 3;
9986         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9987         {
9988                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9989                 if (mesh->numtriangles < mesh->maxtriangles)
9990                 {
9991                         *e++ = element[0];
9992                         *e++ = element[1];
9993                         *e++ = element[2];
9994                         mesh->numtriangles++;
9995                 }
9996                 element[1] = element[2];
9997         }
9998 }
9999
10000 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10001 {
10002         int i;
10003         int *e, element[3];
10004         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10005         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10006         e = mesh->element3i + mesh->numtriangles * 3;
10007         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10008         {
10009                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10010                 if (mesh->numtriangles < mesh->maxtriangles)
10011                 {
10012                         *e++ = element[0];
10013                         *e++ = element[1];
10014                         *e++ = element[2];
10015                         mesh->numtriangles++;
10016                 }
10017                 element[1] = element[2];
10018         }
10019 }
10020
10021 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10022 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10023 {
10024         int planenum, planenum2;
10025         int w;
10026         int tempnumpoints;
10027         mplane_t *plane, *plane2;
10028         double maxdist;
10029         double temppoints[2][256*3];
10030         // figure out how large a bounding box we need to properly compute this brush
10031         maxdist = 0;
10032         for (w = 0;w < numplanes;w++)
10033                 maxdist = max(maxdist, fabs(planes[w].dist));
10034         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10035         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10036         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10037         {
10038                 w = 0;
10039                 tempnumpoints = 4;
10040                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10041                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10042                 {
10043                         if (planenum2 == planenum)
10044                                 continue;
10045                         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);
10046                         w = !w;
10047                 }
10048                 if (tempnumpoints < 3)
10049                         continue;
10050                 // generate elements forming a triangle fan for this polygon
10051                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10052         }
10053 }
10054
10055 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)
10056 {
10057         texturelayer_t *layer;
10058         layer = t->currentlayers + t->currentnumlayers++;
10059         layer->type = type;
10060         layer->depthmask = depthmask;
10061         layer->blendfunc1 = blendfunc1;
10062         layer->blendfunc2 = blendfunc2;
10063         layer->texture = texture;
10064         layer->texmatrix = *matrix;
10065         layer->color[0] = r;
10066         layer->color[1] = g;
10067         layer->color[2] = b;
10068         layer->color[3] = a;
10069 }
10070
10071 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10072 {
10073         if(parms[0] == 0 && parms[1] == 0)
10074                 return false;
10075         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10076                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10077                         return false;
10078         return true;
10079 }
10080
10081 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10082 {
10083         double index, f;
10084         index = parms[2] + r_refdef.scene.time * parms[3];
10085         index -= floor(index);
10086         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10087         {
10088         default:
10089         case Q3WAVEFUNC_NONE:
10090         case Q3WAVEFUNC_NOISE:
10091         case Q3WAVEFUNC_COUNT:
10092                 f = 0;
10093                 break;
10094         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10095         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10096         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10097         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10098         case Q3WAVEFUNC_TRIANGLE:
10099                 index *= 4;
10100                 f = index - floor(index);
10101                 if (index < 1)
10102                         f = f;
10103                 else if (index < 2)
10104                         f = 1 - f;
10105                 else if (index < 3)
10106                         f = -f;
10107                 else
10108                         f = -(1 - f);
10109                 break;
10110         }
10111         f = parms[0] + parms[1] * f;
10112         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10113                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10114         return (float) f;
10115 }
10116
10117 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10118 {
10119         int w, h, idx;
10120         float f;
10121         float tcmat[12];
10122         matrix4x4_t matrix, temp;
10123         switch(tcmod->tcmod)
10124         {
10125                 case Q3TCMOD_COUNT:
10126                 case Q3TCMOD_NONE:
10127                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10128                                 matrix = r_waterscrollmatrix;
10129                         else
10130                                 matrix = identitymatrix;
10131                         break;
10132                 case Q3TCMOD_ENTITYTRANSLATE:
10133                         // this is used in Q3 to allow the gamecode to control texcoord
10134                         // scrolling on the entity, which is not supported in darkplaces yet.
10135                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10136                         break;
10137                 case Q3TCMOD_ROTATE:
10138                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10139                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10140                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10141                         break;
10142                 case Q3TCMOD_SCALE:
10143                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10144                         break;
10145                 case Q3TCMOD_SCROLL:
10146                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10147                         break;
10148                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10149                         w = (int) tcmod->parms[0];
10150                         h = (int) tcmod->parms[1];
10151                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10152                         f = f - floor(f);
10153                         idx = (int) floor(f * w * h);
10154                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10155                         break;
10156                 case Q3TCMOD_STRETCH:
10157                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10158                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10159                         break;
10160                 case Q3TCMOD_TRANSFORM:
10161                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10162                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10163                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10164                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10165                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10166                         break;
10167                 case Q3TCMOD_TURBULENT:
10168                         // this is handled in the RSurf_PrepareVertices function
10169                         matrix = identitymatrix;
10170                         break;
10171         }
10172         temp = *texmatrix;
10173         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10174 }
10175
10176 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10177 {
10178         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10179         char name[MAX_QPATH];
10180         skinframe_t *skinframe;
10181         unsigned char pixels[296*194];
10182         strlcpy(cache->name, skinname, sizeof(cache->name));
10183         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10184         if (developer_loading.integer)
10185                 Con_Printf("loading %s\n", name);
10186         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10187         if (!skinframe || !skinframe->base)
10188         {
10189                 unsigned char *f;
10190                 fs_offset_t filesize;
10191                 skinframe = NULL;
10192                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10193                 if (f)
10194                 {
10195                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10196                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10197                         Mem_Free(f);
10198                 }
10199         }
10200         cache->skinframe = skinframe;
10201 }
10202
10203 texture_t *R_GetCurrentTexture(texture_t *t)
10204 {
10205         int i;
10206         const entity_render_t *ent = rsurface.entity;
10207         dp_model_t *model = ent->model;
10208         q3shaderinfo_layer_tcmod_t *tcmod;
10209
10210         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10211                 return t->currentframe;
10212         t->update_lastrenderframe = r_textureframe;
10213         t->update_lastrenderentity = (void *)ent;
10214
10215         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10216                 t->camera_entity = ent->entitynumber;
10217         else
10218                 t->camera_entity = 0;
10219
10220         // switch to an alternate material if this is a q1bsp animated material
10221         {
10222                 texture_t *texture = t;
10223                 int s = rsurface.ent_skinnum;
10224                 if ((unsigned int)s >= (unsigned int)model->numskins)
10225                         s = 0;
10226                 if (model->skinscenes)
10227                 {
10228                         if (model->skinscenes[s].framecount > 1)
10229                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10230                         else
10231                                 s = model->skinscenes[s].firstframe;
10232                 }
10233                 if (s > 0)
10234                         t = t + s * model->num_surfaces;
10235                 if (t->animated)
10236                 {
10237                         // use an alternate animation if the entity's frame is not 0,
10238                         // and only if the texture has an alternate animation
10239                         if (rsurface.ent_alttextures && t->anim_total[1])
10240                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10241                         else
10242                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10243                 }
10244                 texture->currentframe = t;
10245         }
10246
10247         // update currentskinframe to be a qw skin or animation frame
10248         if (rsurface.ent_qwskin >= 0)
10249         {
10250                 i = rsurface.ent_qwskin;
10251                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10252                 {
10253                         r_qwskincache_size = cl.maxclients;
10254                         if (r_qwskincache)
10255                                 Mem_Free(r_qwskincache);
10256                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10257                 }
10258                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10259                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10260                 t->currentskinframe = r_qwskincache[i].skinframe;
10261                 if (t->currentskinframe == NULL)
10262                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10263         }
10264         else if (t->numskinframes >= 2)
10265                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10266         if (t->backgroundnumskinframes >= 2)
10267                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10268
10269         t->currentmaterialflags = t->basematerialflags;
10270         t->currentalpha = rsurface.colormod[3];
10271         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10272                 t->currentalpha *= r_wateralpha.value;
10273         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10274                 t->currentalpha *= t->r_water_wateralpha;
10275         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10276                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10277         if (!(rsurface.ent_flags & RENDER_LIGHT))
10278                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10279         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10280         {
10281                 // pick a model lighting mode
10282                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10283                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10284                 else
10285                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10286         }
10287         if (rsurface.ent_flags & RENDER_ADDITIVE)
10288                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10289         else if (t->currentalpha < 1)
10290                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10291         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10292                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10293         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10294                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10295         if (t->backgroundnumskinframes)
10296                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10297         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10298         {
10299                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10300                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10301         }
10302         else
10303                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10304         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10305                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10306
10307         // there is no tcmod
10308         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10309         {
10310                 t->currenttexmatrix = r_waterscrollmatrix;
10311                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10312         }
10313         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10314         {
10315                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10316                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10317         }
10318
10319         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10320                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10321         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10322                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10323
10324         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10325         if (t->currentskinframe->qpixels)
10326                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10327         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10328         if (!t->basetexture)
10329                 t->basetexture = r_texture_notexture;
10330         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10331         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10332         t->nmaptexture = t->currentskinframe->nmap;
10333         if (!t->nmaptexture)
10334                 t->nmaptexture = r_texture_blanknormalmap;
10335         t->glosstexture = r_texture_black;
10336         t->glowtexture = t->currentskinframe->glow;
10337         t->fogtexture = t->currentskinframe->fog;
10338         t->reflectmasktexture = t->currentskinframe->reflect;
10339         if (t->backgroundnumskinframes)
10340         {
10341                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10342                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10343                 t->backgroundglosstexture = r_texture_black;
10344                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10345                 if (!t->backgroundnmaptexture)
10346                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10347         }
10348         else
10349         {
10350                 t->backgroundbasetexture = r_texture_white;
10351                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10352                 t->backgroundglosstexture = r_texture_black;
10353                 t->backgroundglowtexture = NULL;
10354         }
10355         t->specularpower = r_shadow_glossexponent.value;
10356         // TODO: store reference values for these in the texture?
10357         t->specularscale = 0;
10358         if (r_shadow_gloss.integer > 0)
10359         {
10360                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10361                 {
10362                         if (r_shadow_glossintensity.value > 0)
10363                         {
10364                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10365                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10366                                 t->specularscale = r_shadow_glossintensity.value;
10367                         }
10368                 }
10369                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10370                 {
10371                         t->glosstexture = r_texture_white;
10372                         t->backgroundglosstexture = r_texture_white;
10373                         t->specularscale = r_shadow_gloss2intensity.value;
10374                         t->specularpower = r_shadow_gloss2exponent.value;
10375                 }
10376         }
10377         t->specularscale *= t->specularscalemod;
10378         t->specularpower *= t->specularpowermod;
10379
10380         // lightmaps mode looks bad with dlights using actual texturing, so turn
10381         // off the colormap and glossmap, but leave the normalmap on as it still
10382         // accurately represents the shading involved
10383         if (gl_lightmaps.integer)
10384         {
10385                 t->basetexture = r_texture_grey128;
10386                 t->pantstexture = r_texture_black;
10387                 t->shirttexture = r_texture_black;
10388                 t->nmaptexture = r_texture_blanknormalmap;
10389                 t->glosstexture = r_texture_black;
10390                 t->glowtexture = NULL;
10391                 t->fogtexture = NULL;
10392                 t->reflectmasktexture = NULL;
10393                 t->backgroundbasetexture = NULL;
10394                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10395                 t->backgroundglosstexture = r_texture_black;
10396                 t->backgroundglowtexture = NULL;
10397                 t->specularscale = 0;
10398                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10399         }
10400
10401         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10402         VectorClear(t->dlightcolor);
10403         t->currentnumlayers = 0;
10404         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10405         {
10406                 int blendfunc1, blendfunc2;
10407                 qboolean depthmask;
10408                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10409                 {
10410                         blendfunc1 = GL_SRC_ALPHA;
10411                         blendfunc2 = GL_ONE;
10412                 }
10413                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10414                 {
10415                         blendfunc1 = GL_SRC_ALPHA;
10416                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10417                 }
10418                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10419                 {
10420                         blendfunc1 = t->customblendfunc[0];
10421                         blendfunc2 = t->customblendfunc[1];
10422                 }
10423                 else
10424                 {
10425                         blendfunc1 = GL_ONE;
10426                         blendfunc2 = GL_ZERO;
10427                 }
10428                 // don't colormod evilblend textures
10429                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10430                         VectorSet(t->lightmapcolor, 1, 1, 1);
10431                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10432                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10433                 {
10434                         // fullbright is not affected by r_refdef.lightmapintensity
10435                         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]);
10436                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10437                                 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]);
10438                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10439                                 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]);
10440                 }
10441                 else
10442                 {
10443                         vec3_t ambientcolor;
10444                         float colorscale;
10445                         // set the color tint used for lights affecting this surface
10446                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10447                         colorscale = 2;
10448                         // q3bsp has no lightmap updates, so the lightstylevalue that
10449                         // would normally be baked into the lightmap must be
10450                         // applied to the color
10451                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10452                         if (model->type == mod_brushq3)
10453                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10454                         colorscale *= r_refdef.lightmapintensity;
10455                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10456                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10457                         // basic lit geometry
10458                         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]);
10459                         // add pants/shirt if needed
10460                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10461                                 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]);
10462                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10463                                 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]);
10464                         // now add ambient passes if needed
10465                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10466                         {
10467                                 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]);
10468                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10469                                         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]);
10470                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10471                                         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]);
10472                         }
10473                 }
10474                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10475                         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]);
10476                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10477                 {
10478                         // if this is opaque use alpha blend which will darken the earlier
10479                         // passes cheaply.
10480                         //
10481                         // if this is an alpha blended material, all the earlier passes
10482                         // were darkened by fog already, so we only need to add the fog
10483                         // color ontop through the fog mask texture
10484                         //
10485                         // if this is an additive blended material, all the earlier passes
10486                         // were darkened by fog already, and we should not add fog color
10487                         // (because the background was not darkened, there is no fog color
10488                         // that was lost behind it).
10489                         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]);
10490                 }
10491         }
10492
10493         return t->currentframe;
10494 }
10495
10496 rsurfacestate_t rsurface;
10497
10498 void R_Mesh_ResizeArrays(int newvertices)
10499 {
10500         unsigned char *base;
10501         size_t size;
10502         if (rsurface.array_size >= newvertices)
10503                 return;
10504         if (rsurface.array_base)
10505                 Mem_Free(rsurface.array_base);
10506         rsurface.array_size = (newvertices + 1023) & ~1023;
10507         size = 0;
10508         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10509         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10510         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10511         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10512         size += rsurface.array_size * sizeof(float[3]);
10513         size += rsurface.array_size * sizeof(float[3]);
10514         size += rsurface.array_size * sizeof(float[3]);
10515         size += rsurface.array_size * sizeof(float[3]);
10516         size += rsurface.array_size * sizeof(float[3]);
10517         size += rsurface.array_size * sizeof(float[3]);
10518         size += rsurface.array_size * sizeof(float[3]);
10519         size += rsurface.array_size * sizeof(float[3]);
10520         size += rsurface.array_size * sizeof(float[4]);
10521         size += rsurface.array_size * sizeof(float[2]);
10522         size += rsurface.array_size * sizeof(float[2]);
10523         size += rsurface.array_size * sizeof(float[4]);
10524         size += rsurface.array_size * sizeof(int[3]);
10525         size += rsurface.array_size * sizeof(unsigned short[3]);
10526         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10527         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10528         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10529         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10530         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10531         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10532         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10533         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10534         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10535         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10536         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10537         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10538         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10539         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10540         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10541         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10542         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10543         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10544         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10545 }
10546
10547 void RSurf_ActiveWorldEntity(void)
10548 {
10549         dp_model_t *model = r_refdef.scene.worldmodel;
10550         //if (rsurface.entity == r_refdef.scene.worldentity)
10551         //      return;
10552         rsurface.entity = r_refdef.scene.worldentity;
10553         rsurface.skeleton = NULL;
10554         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10555         rsurface.ent_skinnum = 0;
10556         rsurface.ent_qwskin = -1;
10557         rsurface.ent_shadertime = 0;
10558         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10559         if (rsurface.array_size < model->surfmesh.num_vertices)
10560                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10561         rsurface.matrix = identitymatrix;
10562         rsurface.inversematrix = identitymatrix;
10563         rsurface.matrixscale = 1;
10564         rsurface.inversematrixscale = 1;
10565         R_EntityMatrix(&identitymatrix);
10566         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10567         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10568         rsurface.fograngerecip = r_refdef.fograngerecip;
10569         rsurface.fogheightfade = r_refdef.fogheightfade;
10570         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10571         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10572         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10573         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10574         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10575         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10576         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10577         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10578         rsurface.colormod[3] = 1;
10579         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);
10580         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10581         rsurface.frameblend[0].lerp = 1;
10582         rsurface.ent_alttextures = false;
10583         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10584         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10585         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10586         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10587         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10588         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10589         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10590         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10591         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10592         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10593         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10594         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10595         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10596         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10597         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10598         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10599         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10600         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10601         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10602         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10603         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10604         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10605         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10606         rsurface.modelelement3i = model->surfmesh.data_element3i;
10607         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10608         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10609         rsurface.modelelement3s = model->surfmesh.data_element3s;
10610         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10611         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10612         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10613         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10614         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10615         rsurface.modelsurfaces = model->data_surfaces;
10616         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10617         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10618         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10619         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10620         rsurface.modelgeneratedvertex = false;
10621         rsurface.batchgeneratedvertex = false;
10622         rsurface.batchfirstvertex = 0;
10623         rsurface.batchnumvertices = 0;
10624         rsurface.batchfirsttriangle = 0;
10625         rsurface.batchnumtriangles = 0;
10626         rsurface.batchvertex3f  = NULL;
10627         rsurface.batchvertex3f_vertexbuffer = NULL;
10628         rsurface.batchvertex3f_bufferoffset = 0;
10629         rsurface.batchsvector3f = NULL;
10630         rsurface.batchsvector3f_vertexbuffer = NULL;
10631         rsurface.batchsvector3f_bufferoffset = 0;
10632         rsurface.batchtvector3f = NULL;
10633         rsurface.batchtvector3f_vertexbuffer = NULL;
10634         rsurface.batchtvector3f_bufferoffset = 0;
10635         rsurface.batchnormal3f  = NULL;
10636         rsurface.batchnormal3f_vertexbuffer = NULL;
10637         rsurface.batchnormal3f_bufferoffset = 0;
10638         rsurface.batchlightmapcolor4f = NULL;
10639         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10640         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10641         rsurface.batchtexcoordtexture2f = NULL;
10642         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10643         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10644         rsurface.batchtexcoordlightmap2f = NULL;
10645         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10646         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10647         rsurface.batchvertexmesh = NULL;
10648         rsurface.batchvertexmeshbuffer = NULL;
10649         rsurface.batchvertexposition = NULL;
10650         rsurface.batchvertexpositionbuffer = NULL;
10651         rsurface.batchelement3i = NULL;
10652         rsurface.batchelement3i_indexbuffer = NULL;
10653         rsurface.batchelement3i_bufferoffset = 0;
10654         rsurface.batchelement3s = NULL;
10655         rsurface.batchelement3s_indexbuffer = NULL;
10656         rsurface.batchelement3s_bufferoffset = 0;
10657         rsurface.passcolor4f = NULL;
10658         rsurface.passcolor4f_vertexbuffer = NULL;
10659         rsurface.passcolor4f_bufferoffset = 0;
10660 }
10661
10662 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10663 {
10664         dp_model_t *model = ent->model;
10665         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10666         //      return;
10667         rsurface.entity = (entity_render_t *)ent;
10668         rsurface.skeleton = ent->skeleton;
10669         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10670         rsurface.ent_skinnum = ent->skinnum;
10671         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;
10672         rsurface.ent_shadertime = ent->shadertime;
10673         rsurface.ent_flags = ent->flags;
10674         if (rsurface.array_size < model->surfmesh.num_vertices)
10675                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10676         rsurface.matrix = ent->matrix;
10677         rsurface.inversematrix = ent->inversematrix;
10678         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10679         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10680         R_EntityMatrix(&rsurface.matrix);
10681         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10682         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10683         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10684         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10685         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10686         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10687         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10688         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10689         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10690         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10691         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10692         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10693         rsurface.colormod[3] = ent->alpha;
10694         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10695         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10696         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10697         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10698         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10699         if (ent->model->brush.submodel && !prepass)
10700         {
10701                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10702                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10703         }
10704         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10705         {
10706                 if (ent->animcache_vertex3f && !r_framedata_failed)
10707                 {
10708                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10709                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10710                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10711                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10712                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10713                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10714                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10715                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10716                 }
10717                 else if (wanttangents)
10718                 {
10719                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10720                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10721                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10722                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10723                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10724                         rsurface.modelvertexmesh = NULL;
10725                         rsurface.modelvertexmeshbuffer = NULL;
10726                         rsurface.modelvertexposition = NULL;
10727                         rsurface.modelvertexpositionbuffer = NULL;
10728                 }
10729                 else if (wantnormals)
10730                 {
10731                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10732                         rsurface.modelsvector3f = NULL;
10733                         rsurface.modeltvector3f = NULL;
10734                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10735                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10736                         rsurface.modelvertexmesh = NULL;
10737                         rsurface.modelvertexmeshbuffer = NULL;
10738                         rsurface.modelvertexposition = NULL;
10739                         rsurface.modelvertexpositionbuffer = NULL;
10740                 }
10741                 else
10742                 {
10743                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10744                         rsurface.modelsvector3f = NULL;
10745                         rsurface.modeltvector3f = NULL;
10746                         rsurface.modelnormal3f = NULL;
10747                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10748                         rsurface.modelvertexmesh = NULL;
10749                         rsurface.modelvertexmeshbuffer = NULL;
10750                         rsurface.modelvertexposition = NULL;
10751                         rsurface.modelvertexpositionbuffer = NULL;
10752                 }
10753                 rsurface.modelvertex3f_vertexbuffer = 0;
10754                 rsurface.modelvertex3f_bufferoffset = 0;
10755                 rsurface.modelsvector3f_vertexbuffer = 0;
10756                 rsurface.modelsvector3f_bufferoffset = 0;
10757                 rsurface.modeltvector3f_vertexbuffer = 0;
10758                 rsurface.modeltvector3f_bufferoffset = 0;
10759                 rsurface.modelnormal3f_vertexbuffer = 0;
10760                 rsurface.modelnormal3f_bufferoffset = 0;
10761                 rsurface.modelgeneratedvertex = true;
10762         }
10763         else
10764         {
10765                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10766                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10767                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10768                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10769                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10770                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10771                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10772                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10773                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10774                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10775                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10776                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10777                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10778                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10779                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10780                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10781                 rsurface.modelgeneratedvertex = false;
10782         }
10783         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10784         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10785         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10786         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10787         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10788         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10789         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10790         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10791         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10792         rsurface.modelelement3i = model->surfmesh.data_element3i;
10793         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10794         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10795         rsurface.modelelement3s = model->surfmesh.data_element3s;
10796         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10797         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10798         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10799         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10800         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10801         rsurface.modelsurfaces = model->data_surfaces;
10802         rsurface.batchgeneratedvertex = false;
10803         rsurface.batchfirstvertex = 0;
10804         rsurface.batchnumvertices = 0;
10805         rsurface.batchfirsttriangle = 0;
10806         rsurface.batchnumtriangles = 0;
10807         rsurface.batchvertex3f  = NULL;
10808         rsurface.batchvertex3f_vertexbuffer = NULL;
10809         rsurface.batchvertex3f_bufferoffset = 0;
10810         rsurface.batchsvector3f = NULL;
10811         rsurface.batchsvector3f_vertexbuffer = NULL;
10812         rsurface.batchsvector3f_bufferoffset = 0;
10813         rsurface.batchtvector3f = NULL;
10814         rsurface.batchtvector3f_vertexbuffer = NULL;
10815         rsurface.batchtvector3f_bufferoffset = 0;
10816         rsurface.batchnormal3f  = NULL;
10817         rsurface.batchnormal3f_vertexbuffer = NULL;
10818         rsurface.batchnormal3f_bufferoffset = 0;
10819         rsurface.batchlightmapcolor4f = NULL;
10820         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10821         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10822         rsurface.batchtexcoordtexture2f = NULL;
10823         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10824         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10825         rsurface.batchtexcoordlightmap2f = NULL;
10826         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10827         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10828         rsurface.batchvertexmesh = NULL;
10829         rsurface.batchvertexmeshbuffer = NULL;
10830         rsurface.batchvertexposition = NULL;
10831         rsurface.batchvertexpositionbuffer = NULL;
10832         rsurface.batchelement3i = NULL;
10833         rsurface.batchelement3i_indexbuffer = NULL;
10834         rsurface.batchelement3i_bufferoffset = 0;
10835         rsurface.batchelement3s = NULL;
10836         rsurface.batchelement3s_indexbuffer = NULL;
10837         rsurface.batchelement3s_bufferoffset = 0;
10838         rsurface.passcolor4f = NULL;
10839         rsurface.passcolor4f_vertexbuffer = NULL;
10840         rsurface.passcolor4f_bufferoffset = 0;
10841 }
10842
10843 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)
10844 {
10845         int i;
10846
10847         rsurface.entity = r_refdef.scene.worldentity;
10848         rsurface.skeleton = NULL;
10849         rsurface.ent_skinnum = 0;
10850         rsurface.ent_qwskin = -1;
10851         rsurface.ent_shadertime = shadertime;
10852         rsurface.ent_flags = entflags;
10853         rsurface.modelnumvertices = numvertices;
10854         rsurface.modelnumtriangles = numtriangles;
10855         if (rsurface.array_size < rsurface.modelnumvertices)
10856                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10857         rsurface.matrix = *matrix;
10858         rsurface.inversematrix = *inversematrix;
10859         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10860         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10861         R_EntityMatrix(&rsurface.matrix);
10862         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10863         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10864         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10865         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10866         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10867         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10868         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10869         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10870         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10871         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10872         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10873         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10874         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);
10875         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10876         rsurface.frameblend[0].lerp = 1;
10877         rsurface.ent_alttextures = false;
10878         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10879         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10880         if (wanttangents)
10881         {
10882                 rsurface.modelvertex3f = vertex3f;
10883                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10884                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10885                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10886         }
10887         else if (wantnormals)
10888         {
10889                 rsurface.modelvertex3f = vertex3f;
10890                 rsurface.modelsvector3f = NULL;
10891                 rsurface.modeltvector3f = NULL;
10892                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10893         }
10894         else
10895         {
10896                 rsurface.modelvertex3f = vertex3f;
10897                 rsurface.modelsvector3f = NULL;
10898                 rsurface.modeltvector3f = NULL;
10899                 rsurface.modelnormal3f = NULL;
10900         }
10901         rsurface.modelvertexmesh = NULL;
10902         rsurface.modelvertexmeshbuffer = NULL;
10903         rsurface.modelvertexposition = NULL;
10904         rsurface.modelvertexpositionbuffer = NULL;
10905         rsurface.modelvertex3f_vertexbuffer = 0;
10906         rsurface.modelvertex3f_bufferoffset = 0;
10907         rsurface.modelsvector3f_vertexbuffer = 0;
10908         rsurface.modelsvector3f_bufferoffset = 0;
10909         rsurface.modeltvector3f_vertexbuffer = 0;
10910         rsurface.modeltvector3f_bufferoffset = 0;
10911         rsurface.modelnormal3f_vertexbuffer = 0;
10912         rsurface.modelnormal3f_bufferoffset = 0;
10913         rsurface.modelgeneratedvertex = true;
10914         rsurface.modellightmapcolor4f  = color4f;
10915         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10916         rsurface.modellightmapcolor4f_bufferoffset = 0;
10917         rsurface.modeltexcoordtexture2f  = texcoord2f;
10918         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10919         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10920         rsurface.modeltexcoordlightmap2f  = NULL;
10921         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10922         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10923         rsurface.modelelement3i = element3i;
10924         rsurface.modelelement3i_indexbuffer = NULL;
10925         rsurface.modelelement3i_bufferoffset = 0;
10926         rsurface.modelelement3s = element3s;
10927         rsurface.modelelement3s_indexbuffer = NULL;
10928         rsurface.modelelement3s_bufferoffset = 0;
10929         rsurface.modellightmapoffsets = NULL;
10930         rsurface.modelsurfaces = NULL;
10931         rsurface.batchgeneratedvertex = false;
10932         rsurface.batchfirstvertex = 0;
10933         rsurface.batchnumvertices = 0;
10934         rsurface.batchfirsttriangle = 0;
10935         rsurface.batchnumtriangles = 0;
10936         rsurface.batchvertex3f  = NULL;
10937         rsurface.batchvertex3f_vertexbuffer = NULL;
10938         rsurface.batchvertex3f_bufferoffset = 0;
10939         rsurface.batchsvector3f = NULL;
10940         rsurface.batchsvector3f_vertexbuffer = NULL;
10941         rsurface.batchsvector3f_bufferoffset = 0;
10942         rsurface.batchtvector3f = NULL;
10943         rsurface.batchtvector3f_vertexbuffer = NULL;
10944         rsurface.batchtvector3f_bufferoffset = 0;
10945         rsurface.batchnormal3f  = NULL;
10946         rsurface.batchnormal3f_vertexbuffer = NULL;
10947         rsurface.batchnormal3f_bufferoffset = 0;
10948         rsurface.batchlightmapcolor4f = NULL;
10949         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10950         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10951         rsurface.batchtexcoordtexture2f = NULL;
10952         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10953         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10954         rsurface.batchtexcoordlightmap2f = NULL;
10955         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10956         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10957         rsurface.batchvertexmesh = NULL;
10958         rsurface.batchvertexmeshbuffer = NULL;
10959         rsurface.batchvertexposition = NULL;
10960         rsurface.batchvertexpositionbuffer = NULL;
10961         rsurface.batchelement3i = NULL;
10962         rsurface.batchelement3i_indexbuffer = NULL;
10963         rsurface.batchelement3i_bufferoffset = 0;
10964         rsurface.batchelement3s = NULL;
10965         rsurface.batchelement3s_indexbuffer = NULL;
10966         rsurface.batchelement3s_bufferoffset = 0;
10967         rsurface.passcolor4f = NULL;
10968         rsurface.passcolor4f_vertexbuffer = NULL;
10969         rsurface.passcolor4f_bufferoffset = 0;
10970
10971         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10972         {
10973                 if ((wantnormals || wanttangents) && !normal3f)
10974                 {
10975                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10976                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10977                 }
10978                 if (wanttangents && !svector3f)
10979                 {
10980                         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);
10981                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10982                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10983                 }
10984         }
10985
10986         // now convert arrays into vertexmesh structs
10987         for (i = 0;i < numvertices;i++)
10988         {
10989                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10990                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10991                 if (rsurface.modelsvector3f)
10992                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10993                 if (rsurface.modeltvector3f)
10994                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10995                 if (rsurface.modelnormal3f)
10996                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10997                 if (rsurface.modellightmapcolor4f)
10998                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10999                 if (rsurface.modeltexcoordtexture2f)
11000                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11001                 if (rsurface.modeltexcoordlightmap2f)
11002                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11003         }
11004 }
11005
11006 float RSurf_FogPoint(const float *v)
11007 {
11008         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11009         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11010         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11011         float FogHeightFade = r_refdef.fogheightfade;
11012         float fogfrac;
11013         unsigned int fogmasktableindex;
11014         if (r_refdef.fogplaneviewabove)
11015                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11016         else
11017                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11018         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11019         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11020 }
11021
11022 float RSurf_FogVertex(const float *v)
11023 {
11024         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11025         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11026         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11027         float FogHeightFade = rsurface.fogheightfade;
11028         float fogfrac;
11029         unsigned int fogmasktableindex;
11030         if (r_refdef.fogplaneviewabove)
11031                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11032         else
11033                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11034         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11035         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11036 }
11037
11038 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11039 {
11040         int i;
11041         for (i = 0;i < numelements;i++)
11042                 outelement3i[i] = inelement3i[i] + adjust;
11043 }
11044
11045 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11046 extern cvar_t gl_vbo;
11047 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11048 {
11049         int deformindex;
11050         int firsttriangle;
11051         int numtriangles;
11052         int firstvertex;
11053         int endvertex;
11054         int numvertices;
11055         int surfacefirsttriangle;
11056         int surfacenumtriangles;
11057         int surfacefirstvertex;
11058         int surfaceendvertex;
11059         int surfacenumvertices;
11060         int surfaceadjustvertex;
11061         int needsupdate;
11062         int i, j;
11063         qboolean gaps;
11064         qboolean dynamicvertex;
11065         float amplitude;
11066         float animpos;
11067         float scale;
11068         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11069         float waveparms[4];
11070         q3shaderinfo_deform_t *deform;
11071         const msurface_t *surface, *firstsurface;
11072         r_vertexposition_t *vertexposition;
11073         r_vertexmesh_t *vertexmesh;
11074         if (!texturenumsurfaces)
11075                 return;
11076         // find vertex range of this surface batch
11077         gaps = false;
11078         firstsurface = texturesurfacelist[0];
11079         firsttriangle = firstsurface->num_firsttriangle;
11080         numtriangles = 0;
11081         firstvertex = endvertex = firstsurface->num_firstvertex;
11082         for (i = 0;i < texturenumsurfaces;i++)
11083         {
11084                 surface = texturesurfacelist[i];
11085                 if (surface != firstsurface + i)
11086                         gaps = true;
11087                 surfacefirstvertex = surface->num_firstvertex;
11088                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11089                 surfacenumtriangles = surface->num_triangles;
11090                 if (firstvertex > surfacefirstvertex)
11091                         firstvertex = surfacefirstvertex;
11092                 if (endvertex < surfaceendvertex)
11093                         endvertex = surfaceendvertex;
11094                 numtriangles += surfacenumtriangles;
11095         }
11096         if (!numtriangles)
11097                 return;
11098
11099         // we now know the vertex range used, and if there are any gaps in it
11100         rsurface.batchfirstvertex = firstvertex;
11101         rsurface.batchnumvertices = endvertex - firstvertex;
11102         rsurface.batchfirsttriangle = firsttriangle;
11103         rsurface.batchnumtriangles = numtriangles;
11104
11105         // this variable holds flags for which properties have been updated that
11106         // may require regenerating vertexmesh or vertexposition arrays...
11107         needsupdate = 0;
11108
11109         // check if any dynamic vertex processing must occur
11110         dynamicvertex = false;
11111
11112         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11113                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11114         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11115         {
11116                 switch (deform->deform)
11117                 {
11118                 default:
11119                 case Q3DEFORM_PROJECTIONSHADOW:
11120                 case Q3DEFORM_TEXT0:
11121                 case Q3DEFORM_TEXT1:
11122                 case Q3DEFORM_TEXT2:
11123                 case Q3DEFORM_TEXT3:
11124                 case Q3DEFORM_TEXT4:
11125                 case Q3DEFORM_TEXT5:
11126                 case Q3DEFORM_TEXT6:
11127                 case Q3DEFORM_TEXT7:
11128                 case Q3DEFORM_NONE:
11129                         break;
11130                 case Q3DEFORM_AUTOSPRITE:
11131                         dynamicvertex = true;
11132                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11133                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11134                         break;
11135                 case Q3DEFORM_AUTOSPRITE2:
11136                         dynamicvertex = true;
11137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11138                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11139                         break;
11140                 case Q3DEFORM_NORMAL:
11141                         dynamicvertex = true;
11142                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11143                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11144                         break;
11145                 case Q3DEFORM_WAVE:
11146                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11147                                 break; // if wavefunc is a nop, ignore this transform
11148                         dynamicvertex = true;
11149                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11150                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11151                         break;
11152                 case Q3DEFORM_BULGE:
11153                         dynamicvertex = true;
11154                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11155                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11156                         break;
11157                 case Q3DEFORM_MOVE:
11158                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11159                                 break; // if wavefunc is a nop, ignore this transform
11160                         dynamicvertex = true;
11161                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11162                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11163                         break;
11164                 }
11165         }
11166         switch(rsurface.texture->tcgen.tcgen)
11167         {
11168         default:
11169         case Q3TCGEN_TEXTURE:
11170                 break;
11171         case Q3TCGEN_LIGHTMAP:
11172                 dynamicvertex = true;
11173                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11174                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11175                 break;
11176         case Q3TCGEN_VECTOR:
11177                 dynamicvertex = true;
11178                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11179                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11180                 break;
11181         case Q3TCGEN_ENVIRONMENT:
11182                 dynamicvertex = true;
11183                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11184                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11185                 break;
11186         }
11187         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11188         {
11189                 dynamicvertex = true;
11190                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11191                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11192         }
11193
11194         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11195         {
11196                 dynamicvertex = true;
11197                 batchneed |= BATCHNEED_NOGAPS;
11198                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11199         }
11200
11201         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11202         {
11203                 dynamicvertex = true;
11204                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11205                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11206         }
11207
11208         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11209         {
11210                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11211                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11212                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11213                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11214                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11215                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11216                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11217         }
11218
11219         // when the model data has no vertex buffer (dynamic mesh), we need to
11220         // eliminate gaps
11221         if (!rsurface.modelvertexmeshbuffer)
11222                 batchneed |= BATCHNEED_NOGAPS;
11223
11224         // if needsupdate, we have to do a dynamic vertex batch for sure
11225         if (needsupdate & batchneed)
11226                 dynamicvertex = true;
11227
11228         // see if we need to build vertexmesh from arrays
11229         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11230                 dynamicvertex = true;
11231
11232         // see if we need to build vertexposition from arrays
11233         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11234                 dynamicvertex = true;
11235
11236         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11237         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11238                 dynamicvertex = true;
11239
11240         // if there is a chance of animated vertex colors, it's a dynamic batch
11241         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11242                 dynamicvertex = true;
11243
11244         rsurface.batchvertex3f = rsurface.modelvertex3f;
11245         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11246         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11247         rsurface.batchsvector3f = rsurface.modelsvector3f;
11248         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11249         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11250         rsurface.batchtvector3f = rsurface.modeltvector3f;
11251         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11252         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11253         rsurface.batchnormal3f = rsurface.modelnormal3f;
11254         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11255         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11256         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11257         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11258         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11259         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11260         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11261         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11262         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11263         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11264         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11265         rsurface.batchvertexposition = rsurface.modelvertexposition;
11266         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11267         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11268         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11269         rsurface.batchelement3i = rsurface.modelelement3i;
11270         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11271         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11272         rsurface.batchelement3s = rsurface.modelelement3s;
11273         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11274         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11275
11276         // if any dynamic vertex processing has to occur in software, we copy the
11277         // entire surface list together before processing to rebase the vertices
11278         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11279         //
11280         // if any gaps exist and we do not have a static vertex buffer, we have to
11281         // copy the surface list together to avoid wasting upload bandwidth on the
11282         // vertices in the gaps.
11283         //
11284         // if gaps exist and we have a static vertex buffer, we still have to
11285         // combine the index buffer ranges into one dynamic index buffer.
11286         //
11287         // in all cases we end up with data that can be drawn in one call.
11288
11289         if (!dynamicvertex)
11290         {
11291                 // static vertex data, just set pointers...
11292                 rsurface.batchgeneratedvertex = false;
11293                 // if there are gaps, we want to build a combined index buffer,
11294                 // otherwise use the original static buffer with an appropriate offset
11295                 if (gaps)
11296                 {
11297                         firsttriangle = 0;
11298                         numtriangles = 0;
11299                         for (i = 0;i < texturenumsurfaces;i++)
11300                         {
11301                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11302                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11303                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11304                                 numtriangles += surfacenumtriangles;
11305                         }
11306                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11307                         rsurface.batchelement3i_indexbuffer = NULL;
11308                         rsurface.batchelement3i_bufferoffset = 0;
11309                         rsurface.batchelement3s = NULL;
11310                         rsurface.batchelement3s_indexbuffer = NULL;
11311                         rsurface.batchelement3s_bufferoffset = 0;
11312                         if (endvertex <= 65536)
11313                         {
11314                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11315                                 for (i = 0;i < numtriangles*3;i++)
11316                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11317                         }
11318                         rsurface.batchfirsttriangle = firsttriangle;
11319                         rsurface.batchnumtriangles = numtriangles;
11320                 }
11321                 return;
11322         }
11323
11324         // something needs software processing, do it for real...
11325         // we only directly handle interleaved array data in this case...
11326         rsurface.batchgeneratedvertex = true;
11327
11328         // now copy the vertex data into a combined array and make an index array
11329         // (this is what Quake3 does all the time)
11330         //if (gaps || rsurface.batchfirstvertex)
11331         {
11332                 rsurface.batchvertexposition = NULL;
11333                 rsurface.batchvertexpositionbuffer = NULL;
11334                 rsurface.batchvertexmesh = NULL;
11335                 rsurface.batchvertexmeshbuffer = NULL;
11336                 rsurface.batchvertex3f = NULL;
11337                 rsurface.batchvertex3f_vertexbuffer = NULL;
11338                 rsurface.batchvertex3f_bufferoffset = 0;
11339                 rsurface.batchsvector3f = NULL;
11340                 rsurface.batchsvector3f_vertexbuffer = NULL;
11341                 rsurface.batchsvector3f_bufferoffset = 0;
11342                 rsurface.batchtvector3f = NULL;
11343                 rsurface.batchtvector3f_vertexbuffer = NULL;
11344                 rsurface.batchtvector3f_bufferoffset = 0;
11345                 rsurface.batchnormal3f = NULL;
11346                 rsurface.batchnormal3f_vertexbuffer = NULL;
11347                 rsurface.batchnormal3f_bufferoffset = 0;
11348                 rsurface.batchlightmapcolor4f = NULL;
11349                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11350                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11351                 rsurface.batchtexcoordtexture2f = NULL;
11352                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11353                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11354                 rsurface.batchtexcoordlightmap2f = NULL;
11355                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11356                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11357                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11358                 rsurface.batchelement3i_indexbuffer = NULL;
11359                 rsurface.batchelement3i_bufferoffset = 0;
11360                 rsurface.batchelement3s = NULL;
11361                 rsurface.batchelement3s_indexbuffer = NULL;
11362                 rsurface.batchelement3s_bufferoffset = 0;
11363                 // we'll only be setting up certain arrays as needed
11364                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11365                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11366                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11367                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11368                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11369                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11370                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11371                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11372                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11373                 {
11374                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11375                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11376                 }
11377                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11378                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11379                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11380                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11381                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11382                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11383                 numvertices = 0;
11384                 numtriangles = 0;
11385                 for (i = 0;i < texturenumsurfaces;i++)
11386                 {
11387                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11388                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11389                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11390                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11391                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11392                         // copy only the data requested
11393                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11394                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11395                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11396                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11397                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11398                         {
11399                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11400                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11401                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11402                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11403                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11404                                 {
11405                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11406                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11407                                 }
11408                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11409                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11410                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11411                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11412                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11413                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11414                         }
11415                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11416                         numvertices += surfacenumvertices;
11417                         numtriangles += surfacenumtriangles;
11418                 }
11419
11420                 // generate a 16bit index array as well if possible
11421                 // (in general, dynamic batches fit)
11422                 if (numvertices <= 65536)
11423                 {
11424                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11425                         for (i = 0;i < numtriangles*3;i++)
11426                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11427                 }
11428
11429                 // since we've copied everything, the batch now starts at 0
11430                 rsurface.batchfirstvertex = 0;
11431                 rsurface.batchnumvertices = numvertices;
11432                 rsurface.batchfirsttriangle = 0;
11433                 rsurface.batchnumtriangles = numtriangles;
11434         }
11435
11436         // q1bsp surfaces rendered in vertex color mode have to have colors
11437         // calculated based on lightstyles
11438         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11439         {
11440                 // generate color arrays for the surfaces in this list
11441                 int c[4];
11442                 int scale;
11443                 int size3;
11444                 const int *offsets;
11445                 const unsigned char *lm;
11446                 numvertices = 0;
11447                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11448                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11449                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11450                 for (i = 0;i < texturenumsurfaces;i++)
11451                 {
11452                         surface = texturesurfacelist[i];
11453                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11454                         surfacenumvertices = surface->num_vertices;
11455                         if (surface->lightmapinfo->samples)
11456                         {
11457                                 for (j = 0;j < surfacenumvertices;j++)
11458                                 {
11459                                         lm = surface->lightmapinfo->samples + offsets[j];
11460                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11461                                         VectorScale(lm, scale, c);
11462                                         if (surface->lightmapinfo->styles[1] != 255)
11463                                         {
11464                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11465                                                 lm += size3;
11466                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11467                                                 VectorMA(c, scale, lm, c);
11468                                                 if (surface->lightmapinfo->styles[2] != 255)
11469                                                 {
11470                                                         lm += size3;
11471                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11472                                                         VectorMA(c, scale, lm, c);
11473                                                         if (surface->lightmapinfo->styles[3] != 255)
11474                                                         {
11475                                                                 lm += size3;
11476                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11477                                                                 VectorMA(c, scale, lm, c);
11478                                                         }
11479                                                 }
11480                                         }
11481                                         c[0] >>= 15;
11482                                         c[1] >>= 15;
11483                                         c[2] >>= 15;
11484                                         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);
11485                                         numvertices++;
11486                                 }
11487                         }
11488                         else
11489                         {
11490                                 for (j = 0;j < surfacenumvertices;j++)
11491                                 {
11492                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11493                                         numvertices++;
11494                                 }
11495                         }
11496                 }
11497         }
11498
11499         // if vertices are deformed (sprite flares and things in maps, possibly
11500         // water waves, bulges and other deformations), modify the copied vertices
11501         // in place
11502         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11503         {
11504                 switch (deform->deform)
11505                 {
11506                 default:
11507                 case Q3DEFORM_PROJECTIONSHADOW:
11508                 case Q3DEFORM_TEXT0:
11509                 case Q3DEFORM_TEXT1:
11510                 case Q3DEFORM_TEXT2:
11511                 case Q3DEFORM_TEXT3:
11512                 case Q3DEFORM_TEXT4:
11513                 case Q3DEFORM_TEXT5:
11514                 case Q3DEFORM_TEXT6:
11515                 case Q3DEFORM_TEXT7:
11516                 case Q3DEFORM_NONE:
11517                         break;
11518                 case Q3DEFORM_AUTOSPRITE:
11519                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11520                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11521                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11522                         VectorNormalize(newforward);
11523                         VectorNormalize(newright);
11524                         VectorNormalize(newup);
11525                         // a single autosprite surface can contain multiple sprites...
11526                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11527                         {
11528                                 VectorClear(center);
11529                                 for (i = 0;i < 4;i++)
11530                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11531                                 VectorScale(center, 0.25f, center);
11532                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11533                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11534                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11535                                 for (i = 0;i < 4;i++)
11536                                 {
11537                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11538                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11539                                 }
11540                         }
11541                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11542                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11543                         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);
11544                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11545                         rsurface.batchvertex3f_vertexbuffer = NULL;
11546                         rsurface.batchvertex3f_bufferoffset = 0;
11547                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11548                         rsurface.batchsvector3f_vertexbuffer = NULL;
11549                         rsurface.batchsvector3f_bufferoffset = 0;
11550                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11551                         rsurface.batchtvector3f_vertexbuffer = NULL;
11552                         rsurface.batchtvector3f_bufferoffset = 0;
11553                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11554                         rsurface.batchnormal3f_vertexbuffer = NULL;
11555                         rsurface.batchnormal3f_bufferoffset = 0;
11556                         break;
11557                 case Q3DEFORM_AUTOSPRITE2:
11558                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11559                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11560                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11561                         VectorNormalize(newforward);
11562                         VectorNormalize(newright);
11563                         VectorNormalize(newup);
11564                         {
11565                                 const float *v1, *v2;
11566                                 vec3_t start, end;
11567                                 float f, l;
11568                                 struct
11569                                 {
11570                                         float length2;
11571                                         const float *v1;
11572                                         const float *v2;
11573                                 }
11574                                 shortest[2];
11575                                 memset(shortest, 0, sizeof(shortest));
11576                                 // a single autosprite surface can contain multiple sprites...
11577                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11578                                 {
11579                                         VectorClear(center);
11580                                         for (i = 0;i < 4;i++)
11581                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11582                                         VectorScale(center, 0.25f, center);
11583                                         // find the two shortest edges, then use them to define the
11584                                         // axis vectors for rotating around the central axis
11585                                         for (i = 0;i < 6;i++)
11586                                         {
11587                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11588                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11589                                                 l = VectorDistance2(v1, v2);
11590                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11591                                                 if (v1[2] != v2[2])
11592                                                         l += (1.0f / 1024.0f);
11593                                                 if (shortest[0].length2 > l || i == 0)
11594                                                 {
11595                                                         shortest[1] = shortest[0];
11596                                                         shortest[0].length2 = l;
11597                                                         shortest[0].v1 = v1;
11598                                                         shortest[0].v2 = v2;
11599                                                 }
11600                                                 else if (shortest[1].length2 > l || i == 1)
11601                                                 {
11602                                                         shortest[1].length2 = l;
11603                                                         shortest[1].v1 = v1;
11604                                                         shortest[1].v2 = v2;
11605                                                 }
11606                                         }
11607                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11608                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11609                                         // this calculates the right vector from the shortest edge
11610                                         // and the up vector from the edge midpoints
11611                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11612                                         VectorNormalize(right);
11613                                         VectorSubtract(end, start, up);
11614                                         VectorNormalize(up);
11615                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11616                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11617                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11618                                         VectorNegate(forward, forward);
11619                                         VectorReflect(forward, 0, up, forward);
11620                                         VectorNormalize(forward);
11621                                         CrossProduct(up, forward, newright);
11622                                         VectorNormalize(newright);
11623                                         // rotate the quad around the up axis vector, this is made
11624                                         // especially easy by the fact we know the quad is flat,
11625                                         // so we only have to subtract the center position and
11626                                         // measure distance along the right vector, and then
11627                                         // multiply that by the newright vector and add back the
11628                                         // center position
11629                                         // we also need to subtract the old position to undo the
11630                                         // displacement from the center, which we do with a
11631                                         // DotProduct, the subtraction/addition of center is also
11632                                         // optimized into DotProducts here
11633                                         l = DotProduct(right, center);
11634                                         for (i = 0;i < 4;i++)
11635                                         {
11636                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11637                                                 f = DotProduct(right, v1) - l;
11638                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11639                                         }
11640                                 }
11641                         }
11642                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11643                         rsurface.batchvertex3f_vertexbuffer = NULL;
11644                         rsurface.batchvertex3f_bufferoffset = 0;
11645                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11646                         {
11647                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11648                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11649                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11650                                 rsurface.batchnormal3f_bufferoffset = 0;
11651                         }
11652                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11653                         {
11654                                 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);
11655                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11656                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11657                                 rsurface.batchsvector3f_bufferoffset = 0;
11658                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11659                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11660                                 rsurface.batchtvector3f_bufferoffset = 0;
11661                         }
11662                         break;
11663                 case Q3DEFORM_NORMAL:
11664                         // deform the normals to make reflections wavey
11665                         for (j = 0;j < rsurface.batchnumvertices;j++)
11666                         {
11667                                 float vertex[3];
11668                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11669                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11670                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11671                                 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]);
11672                                 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]);
11673                                 VectorNormalize(normal);
11674                         }
11675                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11676                         rsurface.batchnormal3f_vertexbuffer = NULL;
11677                         rsurface.batchnormal3f_bufferoffset = 0;
11678                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11679                         {
11680                                 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);
11681                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11682                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11683                                 rsurface.batchsvector3f_bufferoffset = 0;
11684                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11685                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11686                                 rsurface.batchtvector3f_bufferoffset = 0;
11687                         }
11688                         break;
11689                 case Q3DEFORM_WAVE:
11690                         // deform vertex array to make wavey water and flags and such
11691                         waveparms[0] = deform->waveparms[0];
11692                         waveparms[1] = deform->waveparms[1];
11693                         waveparms[2] = deform->waveparms[2];
11694                         waveparms[3] = deform->waveparms[3];
11695                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11696                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11697                         // this is how a divisor of vertex influence on deformation
11698                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11699                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11700                         for (j = 0;j < rsurface.batchnumvertices;j++)
11701                         {
11702                                 // if the wavefunc depends on time, evaluate it per-vertex
11703                                 if (waveparms[3])
11704                                 {
11705                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11706                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11707                                 }
11708                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11709                         }
11710                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11711                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11712                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11713                         rsurface.batchvertex3f_vertexbuffer = NULL;
11714                         rsurface.batchvertex3f_bufferoffset = 0;
11715                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11716                         rsurface.batchnormal3f_vertexbuffer = NULL;
11717                         rsurface.batchnormal3f_bufferoffset = 0;
11718                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11719                         {
11720                                 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);
11721                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11722                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11723                                 rsurface.batchsvector3f_bufferoffset = 0;
11724                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11725                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11726                                 rsurface.batchtvector3f_bufferoffset = 0;
11727                         }
11728                         break;
11729                 case Q3DEFORM_BULGE:
11730                         // deform vertex array to make the surface have moving bulges
11731                         for (j = 0;j < rsurface.batchnumvertices;j++)
11732                         {
11733                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11734                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11735                         }
11736                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11737                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11738                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11739                         rsurface.batchvertex3f_vertexbuffer = NULL;
11740                         rsurface.batchvertex3f_bufferoffset = 0;
11741                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11742                         rsurface.batchnormal3f_vertexbuffer = NULL;
11743                         rsurface.batchnormal3f_bufferoffset = 0;
11744                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11745                         {
11746                                 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);
11747                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11748                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11749                                 rsurface.batchsvector3f_bufferoffset = 0;
11750                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11751                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11752                                 rsurface.batchtvector3f_bufferoffset = 0;
11753                         }
11754                         break;
11755                 case Q3DEFORM_MOVE:
11756                         // deform vertex array
11757                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11758                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11759                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11760                         VectorScale(deform->parms, scale, waveparms);
11761                         for (j = 0;j < rsurface.batchnumvertices;j++)
11762                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11763                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11764                         rsurface.batchvertex3f_vertexbuffer = NULL;
11765                         rsurface.batchvertex3f_bufferoffset = 0;
11766                         break;
11767                 }
11768         }
11769
11770         // generate texcoords based on the chosen texcoord source
11771         switch(rsurface.texture->tcgen.tcgen)
11772         {
11773         default:
11774         case Q3TCGEN_TEXTURE:
11775                 break;
11776         case Q3TCGEN_LIGHTMAP:
11777                 if (rsurface.batchtexcoordlightmap2f)
11778                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11779                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11780                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11781                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11782                 break;
11783         case Q3TCGEN_VECTOR:
11784                 for (j = 0;j < rsurface.batchnumvertices;j++)
11785                 {
11786                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11787                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11788                 }
11789                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11790                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11791                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11792                 break;
11793         case Q3TCGEN_ENVIRONMENT:
11794                 // make environment reflections using a spheremap
11795                 for (j = 0;j < rsurface.batchnumvertices;j++)
11796                 {
11797                         // identical to Q3A's method, but executed in worldspace so
11798                         // carried models can be shiny too
11799
11800                         float viewer[3], d, reflected[3], worldreflected[3];
11801
11802                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11803                         // VectorNormalize(viewer);
11804
11805                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11806
11807                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11808                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11809                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11810                         // note: this is proportinal to viewer, so we can normalize later
11811
11812                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11813                         VectorNormalize(worldreflected);
11814
11815                         // note: this sphere map only uses world x and z!
11816                         // so positive and negative y will LOOK THE SAME.
11817                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11818                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11819                 }
11820                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11821                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11822                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11823                 break;
11824         }
11825         // the only tcmod that needs software vertex processing is turbulent, so
11826         // check for it here and apply the changes if needed
11827         // and we only support that as the first one
11828         // (handling a mixture of turbulent and other tcmods would be problematic
11829         //  without punting it entirely to a software path)
11830         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11831         {
11832                 amplitude = rsurface.texture->tcmods[0].parms[1];
11833                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11834                 for (j = 0;j < rsurface.batchnumvertices;j++)
11835                 {
11836                         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);
11837                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11838                 }
11839                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11840                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11841                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11842         }
11843
11844         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11845         {
11846                 // convert the modified arrays to vertex structs
11847                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11848                 rsurface.batchvertexmeshbuffer = NULL;
11849                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11850                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11851                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11852                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11853                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11854                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11855                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11856                 {
11857                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11858                         {
11859                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11860                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11861                         }
11862                 }
11863                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11864                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11865                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11866                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11867                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11868                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11869                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11870                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11871                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11872         }
11873
11874         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11875         {
11876                 // convert the modified arrays to vertex structs
11877                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11878                 rsurface.batchvertexpositionbuffer = NULL;
11879                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11880                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11881                 else
11882                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11883                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11884         }
11885 }
11886
11887 void RSurf_DrawBatch(void)
11888 {
11889         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);
11890 }
11891
11892 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11893 {
11894         // pick the closest matching water plane
11895         int planeindex, vertexindex, bestplaneindex = -1;
11896         float d, bestd;
11897         vec3_t vert;
11898         const float *v;
11899         r_waterstate_waterplane_t *p;
11900         bestd = 0;
11901         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11902         {
11903                 if(p->camera_entity != rsurface.texture->camera_entity)
11904                         continue;
11905                 d = 0;
11906                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11907                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11908                 {
11909                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11910                         d += fabs(PlaneDiff(vert, &p->plane));
11911                 }
11912                 if (bestd > d || bestplaneindex < 0)
11913                 {
11914                         bestd = d;
11915                         bestplaneindex = planeindex;
11916                 }
11917         }
11918         return bestplaneindex;
11919 }
11920
11921 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11922 {
11923         int i;
11924         for (i = 0;i < rsurface.batchnumvertices;i++)
11925                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11926         rsurface.passcolor4f = rsurface.array_passcolor4f;
11927         rsurface.passcolor4f_vertexbuffer = 0;
11928         rsurface.passcolor4f_bufferoffset = 0;
11929 }
11930
11931 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11932 {
11933         int i;
11934         float f;
11935         const float *v;
11936         const float *c;
11937         float *c2;
11938         if (rsurface.passcolor4f)
11939         {
11940                 // generate color arrays
11941                 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)
11942                 {
11943                         f = RSurf_FogVertex(v);
11944                         c2[0] = c[0] * f;
11945                         c2[1] = c[1] * f;
11946                         c2[2] = c[2] * f;
11947                         c2[3] = c[3];
11948                 }
11949         }
11950         else
11951         {
11952                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11953                 {
11954                         f = RSurf_FogVertex(v);
11955                         c2[0] = f;
11956                         c2[1] = f;
11957                         c2[2] = f;
11958                         c2[3] = 1;
11959                 }
11960         }
11961         rsurface.passcolor4f = rsurface.array_passcolor4f;
11962         rsurface.passcolor4f_vertexbuffer = 0;
11963         rsurface.passcolor4f_bufferoffset = 0;
11964 }
11965
11966 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11967 {
11968         int i;
11969         float f;
11970         const float *v;
11971         const float *c;
11972         float *c2;
11973         if (!rsurface.passcolor4f)
11974                 return;
11975         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)
11976         {
11977                 f = RSurf_FogVertex(v);
11978                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11979                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11980                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11981                 c2[3] = c[3];
11982         }
11983         rsurface.passcolor4f = rsurface.array_passcolor4f;
11984         rsurface.passcolor4f_vertexbuffer = 0;
11985         rsurface.passcolor4f_bufferoffset = 0;
11986 }
11987
11988 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11989 {
11990         int i;
11991         const float *c;
11992         float *c2;
11993         if (!rsurface.passcolor4f)
11994                 return;
11995         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11996         {
11997                 c2[0] = c[0] * r;
11998                 c2[1] = c[1] * g;
11999                 c2[2] = c[2] * b;
12000                 c2[3] = c[3] * a;
12001         }
12002         rsurface.passcolor4f = rsurface.array_passcolor4f;
12003         rsurface.passcolor4f_vertexbuffer = 0;
12004         rsurface.passcolor4f_bufferoffset = 0;
12005 }
12006
12007 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12008 {
12009         int i;
12010         const float *c;
12011         float *c2;
12012         if (!rsurface.passcolor4f)
12013                 return;
12014         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12015         {
12016                 c2[0] = c[0] + r_refdef.scene.ambient;
12017                 c2[1] = c[1] + r_refdef.scene.ambient;
12018                 c2[2] = c[2] + r_refdef.scene.ambient;
12019                 c2[3] = c[3];
12020         }
12021         rsurface.passcolor4f = rsurface.array_passcolor4f;
12022         rsurface.passcolor4f_vertexbuffer = 0;
12023         rsurface.passcolor4f_bufferoffset = 0;
12024 }
12025
12026 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12027 {
12028         // TODO: optimize
12029         rsurface.passcolor4f = NULL;
12030         rsurface.passcolor4f_vertexbuffer = 0;
12031         rsurface.passcolor4f_bufferoffset = 0;
12032         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12033         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12034         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12035         GL_Color(r, g, b, a);
12036         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12037         RSurf_DrawBatch();
12038 }
12039
12040 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12041 {
12042         // TODO: optimize applyfog && applycolor case
12043         // just apply fog if necessary, and tint the fog color array if necessary
12044         rsurface.passcolor4f = NULL;
12045         rsurface.passcolor4f_vertexbuffer = 0;
12046         rsurface.passcolor4f_bufferoffset = 0;
12047         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12048         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12049         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12050         GL_Color(r, g, b, a);
12051         RSurf_DrawBatch();
12052 }
12053
12054 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12055 {
12056         // TODO: optimize
12057         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12058         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12059         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12060         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12061         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12062         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12063         GL_Color(r, g, b, a);
12064         RSurf_DrawBatch();
12065 }
12066
12067 static void RSurf_DrawBatch_GL11_ClampColor(void)
12068 {
12069         int i;
12070         const float *c1;
12071         float *c2;
12072         if (!rsurface.passcolor4f)
12073                 return;
12074         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12075         {
12076                 c2[0] = bound(0.0f, c1[0], 1.0f);
12077                 c2[1] = bound(0.0f, c1[1], 1.0f);
12078                 c2[2] = bound(0.0f, c1[2], 1.0f);
12079                 c2[3] = bound(0.0f, c1[3], 1.0f);
12080         }
12081 }
12082
12083 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12084 {
12085         int i;
12086         float f;
12087         float alpha;
12088         const float *v;
12089         const float *n;
12090         float *c;
12091         vec3_t ambientcolor;
12092         vec3_t diffusecolor;
12093         vec3_t lightdir;
12094         // TODO: optimize
12095         // model lighting
12096         VectorCopy(rsurface.modellight_lightdir, lightdir);
12097         f = 0.5f * r_refdef.lightmapintensity;
12098         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12099         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12100         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12101         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12102         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12103         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12104         alpha = *a;
12105         if (VectorLength2(diffusecolor) > 0)
12106         {
12107                 // q3-style directional shading
12108                 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)
12109                 {
12110                         if ((f = DotProduct(n, lightdir)) > 0)
12111                                 VectorMA(ambientcolor, f, diffusecolor, c);
12112                         else
12113                                 VectorCopy(ambientcolor, c);
12114                         c[3] = alpha;
12115                 }
12116                 *r = 1;
12117                 *g = 1;
12118                 *b = 1;
12119                 *a = 1;
12120                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12121                 rsurface.passcolor4f_vertexbuffer = 0;
12122                 rsurface.passcolor4f_bufferoffset = 0;
12123                 *applycolor = false;
12124         }
12125         else
12126         {
12127                 *r = ambientcolor[0];
12128                 *g = ambientcolor[1];
12129                 *b = ambientcolor[2];
12130                 rsurface.passcolor4f = NULL;
12131                 rsurface.passcolor4f_vertexbuffer = 0;
12132                 rsurface.passcolor4f_bufferoffset = 0;
12133         }
12134 }
12135
12136 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12137 {
12138         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12139         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12140         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12141         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12142         GL_Color(r, g, b, a);
12143         RSurf_DrawBatch();
12144 }
12145
12146 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12147 {
12148         int i;
12149         float f;
12150         const float *v;
12151         float *c;
12152         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12153         {
12154                 f = 1 - RSurf_FogVertex(v);
12155                 c[0] = r;
12156                 c[1] = g;
12157                 c[2] = b;
12158                 c[3] = f * a;
12159         }
12160 }
12161
12162 void RSurf_SetupDepthAndCulling(void)
12163 {
12164         // submodels are biased to avoid z-fighting with world surfaces that they
12165         // may be exactly overlapping (avoids z-fighting artifacts on certain
12166         // doors and things in Quake maps)
12167         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12168         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12169         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12170         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12171 }
12172
12173 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12174 {
12175         // transparent sky would be ridiculous
12176         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12177                 return;
12178         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12179         skyrenderlater = true;
12180         RSurf_SetupDepthAndCulling();
12181         GL_DepthMask(true);
12182         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12183         // skymasking on them, and Quake3 never did sky masking (unlike
12184         // software Quake and software Quake2), so disable the sky masking
12185         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12186         // and skymasking also looks very bad when noclipping outside the
12187         // level, so don't use it then either.
12188         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12189         {
12190                 R_Mesh_ResetTextureState();
12191                 if (skyrendermasked)
12192                 {
12193                         R_SetupShader_DepthOrShadow();
12194                         // depth-only (masking)
12195                         GL_ColorMask(0,0,0,0);
12196                         // just to make sure that braindead drivers don't draw
12197                         // anything despite that colormask...
12198                         GL_BlendFunc(GL_ZERO, GL_ONE);
12199                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12200                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12201                 }
12202                 else
12203                 {
12204                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12205                         // fog sky
12206                         GL_BlendFunc(GL_ONE, GL_ZERO);
12207                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12208                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12209                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12210                 }
12211                 RSurf_DrawBatch();
12212                 if (skyrendermasked)
12213                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12214         }
12215         R_Mesh_ResetTextureState();
12216         GL_Color(1, 1, 1, 1);
12217 }
12218
12219 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12220 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12221 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12222 {
12223         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12224                 return;
12225         if (prepass)
12226         {
12227                 // render screenspace normalmap to texture
12228                 GL_DepthMask(true);
12229                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12230                 RSurf_DrawBatch();
12231                 return;
12232         }
12233
12234         // bind lightmap texture
12235
12236         // water/refraction/reflection/camera surfaces have to be handled specially
12237         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12238         {
12239                 int start, end, startplaneindex;
12240                 for (start = 0;start < texturenumsurfaces;start = end)
12241                 {
12242                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12243                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12244                                 ;
12245                         // now that we have a batch using the same planeindex, render it
12246                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12247                         {
12248                                 // render water or distortion background
12249                                 GL_DepthMask(true);
12250                                 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));
12251                                 RSurf_DrawBatch();
12252                                 // blend surface on top
12253                                 GL_DepthMask(false);
12254                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12255                                 RSurf_DrawBatch();
12256                         }
12257                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12258                         {
12259                                 // render surface with reflection texture as input
12260                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12261                                 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));
12262                                 RSurf_DrawBatch();
12263                         }
12264                 }
12265                 return;
12266         }
12267
12268         // render surface batch normally
12269         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12270         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12271         RSurf_DrawBatch();
12272 }
12273
12274 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12275 {
12276         // OpenGL 1.3 path - anything not completely ancient
12277         qboolean applycolor;
12278         qboolean applyfog;
12279         int layerindex;
12280         const texturelayer_t *layer;
12281         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);
12282         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12283
12284         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12285         {
12286                 vec4_t layercolor;
12287                 int layertexrgbscale;
12288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12289                 {
12290                         if (layerindex == 0)
12291                                 GL_AlphaTest(true);
12292                         else
12293                         {
12294                                 GL_AlphaTest(false);
12295                                 GL_DepthFunc(GL_EQUAL);
12296                         }
12297                 }
12298                 GL_DepthMask(layer->depthmask && writedepth);
12299                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12300                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12301                 {
12302                         layertexrgbscale = 4;
12303                         VectorScale(layer->color, 0.25f, layercolor);
12304                 }
12305                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12306                 {
12307                         layertexrgbscale = 2;
12308                         VectorScale(layer->color, 0.5f, layercolor);
12309                 }
12310                 else
12311                 {
12312                         layertexrgbscale = 1;
12313                         VectorScale(layer->color, 1.0f, layercolor);
12314                 }
12315                 layercolor[3] = layer->color[3];
12316                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12317                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12318                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12319                 switch (layer->type)
12320                 {
12321                 case TEXTURELAYERTYPE_LITTEXTURE:
12322                         // single-pass lightmapped texture with 2x rgbscale
12323                         R_Mesh_TexBind(0, r_texture_white);
12324                         R_Mesh_TexMatrix(0, NULL);
12325                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12326                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12327                         R_Mesh_TexBind(1, layer->texture);
12328                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12329                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12330                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12331                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12332                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12333                         else if (rsurface.uselightmaptexture)
12334                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12335                         else
12336                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12337                         break;
12338                 case TEXTURELAYERTYPE_TEXTURE:
12339                         // singletexture unlit texture with transparency support
12340                         R_Mesh_TexBind(0, layer->texture);
12341                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12342                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12343                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12344                         R_Mesh_TexBind(1, 0);
12345                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12346                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12347                         break;
12348                 case TEXTURELAYERTYPE_FOG:
12349                         // singletexture fogging
12350                         if (layer->texture)
12351                         {
12352                                 R_Mesh_TexBind(0, layer->texture);
12353                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12354                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12355                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12356                         }
12357                         else
12358                         {
12359                                 R_Mesh_TexBind(0, 0);
12360                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12361                         }
12362                         R_Mesh_TexBind(1, 0);
12363                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12364                         // generate a color array for the fog pass
12365                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12366                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12367                         RSurf_DrawBatch();
12368                         break;
12369                 default:
12370                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12371                 }
12372         }
12373         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12374         {
12375                 GL_DepthFunc(GL_LEQUAL);
12376                 GL_AlphaTest(false);
12377         }
12378 }
12379
12380 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12381 {
12382         // OpenGL 1.1 - crusty old voodoo path
12383         qboolean applyfog;
12384         int layerindex;
12385         const texturelayer_t *layer;
12386         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);
12387         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12388
12389         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12390         {
12391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12392                 {
12393                         if (layerindex == 0)
12394                                 GL_AlphaTest(true);
12395                         else
12396                         {
12397                                 GL_AlphaTest(false);
12398                                 GL_DepthFunc(GL_EQUAL);
12399                         }
12400                 }
12401                 GL_DepthMask(layer->depthmask && writedepth);
12402                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12403                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12404                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12405                 switch (layer->type)
12406                 {
12407                 case TEXTURELAYERTYPE_LITTEXTURE:
12408                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12409                         {
12410                                 // two-pass lit texture with 2x rgbscale
12411                                 // first the lightmap pass
12412                                 R_Mesh_TexBind(0, r_texture_white);
12413                                 R_Mesh_TexMatrix(0, NULL);
12414                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12415                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12416                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12417                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12418                                 else if (rsurface.uselightmaptexture)
12419                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12420                                 else
12421                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12422                                 // then apply the texture to it
12423                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12424                                 R_Mesh_TexBind(0, layer->texture);
12425                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12426                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12427                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12428                                 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);
12429                         }
12430                         else
12431                         {
12432                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12433                                 R_Mesh_TexBind(0, layer->texture);
12434                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12435                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12436                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12437                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12438                                         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);
12439                                 else
12440                                         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);
12441                         }
12442                         break;
12443                 case TEXTURELAYERTYPE_TEXTURE:
12444                         // singletexture unlit texture with transparency support
12445                         R_Mesh_TexBind(0, layer->texture);
12446                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12447                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12448                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12449                         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);
12450                         break;
12451                 case TEXTURELAYERTYPE_FOG:
12452                         // singletexture fogging
12453                         if (layer->texture)
12454                         {
12455                                 R_Mesh_TexBind(0, layer->texture);
12456                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12457                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12458                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12459                         }
12460                         else
12461                         {
12462                                 R_Mesh_TexBind(0, 0);
12463                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12464                         }
12465                         // generate a color array for the fog pass
12466                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12467                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12468                         RSurf_DrawBatch();
12469                         break;
12470                 default:
12471                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12472                 }
12473         }
12474         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12475         {
12476                 GL_DepthFunc(GL_LEQUAL);
12477                 GL_AlphaTest(false);
12478         }
12479 }
12480
12481 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12482 {
12483         int vi;
12484         int j;
12485         r_vertexgeneric_t *batchvertex;
12486         float c[4];
12487
12488         GL_AlphaTest(false);
12489         R_Mesh_ResetTextureState();
12490         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12491
12492         if(rsurface.texture && rsurface.texture->currentskinframe)
12493         {
12494                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12495                 c[3] *= rsurface.texture->currentalpha;
12496         }
12497         else
12498         {
12499                 c[0] = 1;
12500                 c[1] = 0;
12501                 c[2] = 1;
12502                 c[3] = 1;
12503         }
12504
12505         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12506         {
12507                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12508                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12509                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12510         }
12511
12512         // brighten it up (as texture value 127 means "unlit")
12513         c[0] *= 2 * r_refdef.view.colorscale;
12514         c[1] *= 2 * r_refdef.view.colorscale;
12515         c[2] *= 2 * r_refdef.view.colorscale;
12516
12517         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12518                 c[3] *= r_wateralpha.value;
12519
12520         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12521         {
12522                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12523                 GL_DepthMask(false);
12524         }
12525         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12526         {
12527                 GL_BlendFunc(GL_ONE, GL_ONE);
12528                 GL_DepthMask(false);
12529         }
12530         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12531         {
12532                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12533                 GL_DepthMask(false);
12534         }
12535         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12536         {
12537                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12538                 GL_DepthMask(false);
12539         }
12540         else
12541         {
12542                 GL_BlendFunc(GL_ONE, GL_ZERO);
12543                 GL_DepthMask(writedepth);
12544         }
12545
12546         if (r_showsurfaces.integer == 3)
12547         {
12548                 rsurface.passcolor4f = NULL;
12549
12550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12551                 {
12552                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12553
12554                         rsurface.passcolor4f = NULL;
12555                         rsurface.passcolor4f_vertexbuffer = 0;
12556                         rsurface.passcolor4f_bufferoffset = 0;
12557                 }
12558                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12559                 {
12560                         qboolean applycolor = true;
12561                         float one = 1.0;
12562
12563                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12564
12565                         r_refdef.lightmapintensity = 1;
12566                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12567                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12568                 }
12569                 else
12570                 {
12571                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12572
12573                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12574                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12575                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12576                 }
12577
12578                 if(!rsurface.passcolor4f)
12579                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12580
12581                 RSurf_DrawBatch_GL11_ApplyAmbient();
12582                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12583                 if(r_refdef.fogenabled)
12584                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12585                 RSurf_DrawBatch_GL11_ClampColor();
12586
12587                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12588                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12589                 RSurf_DrawBatch();
12590         }
12591         else if (!r_refdef.view.showdebug)
12592         {
12593                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12594                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12595                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12596                 {
12597                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12598                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12599                 }
12600                 R_Mesh_PrepareVertices_Generic_Unlock();
12601                 RSurf_DrawBatch();
12602         }
12603         else if (r_showsurfaces.integer == 4)
12604         {
12605                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12606                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12607                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12608                 {
12609                         unsigned char c = vi << 3;
12610                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12611                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12612                 }
12613                 R_Mesh_PrepareVertices_Generic_Unlock();
12614                 RSurf_DrawBatch();
12615         }
12616         else if (r_showsurfaces.integer == 2)
12617         {
12618                 const int *e;
12619                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12620                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12621                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12622                 {
12623                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12624                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12625                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12626                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12627                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12628                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12629                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12630                 }
12631                 R_Mesh_PrepareVertices_Generic_Unlock();
12632                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12633         }
12634         else
12635         {
12636                 int texturesurfaceindex;
12637                 int k;
12638                 const msurface_t *surface;
12639                 unsigned char surfacecolor4ub[4];
12640                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12641                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12642                 vi = 0;
12643                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12644                 {
12645                         surface = texturesurfacelist[texturesurfaceindex];
12646                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12647                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12648                         for (j = 0;j < surface->num_vertices;j++)
12649                         {
12650                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12651                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12652                                 vi++;
12653                         }
12654                 }
12655                 R_Mesh_PrepareVertices_Generic_Unlock();
12656                 RSurf_DrawBatch();
12657         }
12658 }
12659
12660 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12661 {
12662         CHECKGLERROR
12663         RSurf_SetupDepthAndCulling();
12664         if (r_showsurfaces.integer)
12665         {
12666                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12667                 return;
12668         }
12669         switch (vid.renderpath)
12670         {
12671         case RENDERPATH_GL20:
12672         case RENDERPATH_CGGL:
12673         case RENDERPATH_D3D9:
12674         case RENDERPATH_D3D10:
12675         case RENDERPATH_D3D11:
12676                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12677                 break;
12678         case RENDERPATH_GL13:
12679                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12680                 break;
12681         case RENDERPATH_GL11:
12682                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12683                 break;
12684         }
12685         CHECKGLERROR
12686 }
12687
12688 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12689 {
12690         CHECKGLERROR
12691         RSurf_SetupDepthAndCulling();
12692         if (r_showsurfaces.integer)
12693         {
12694                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12695                 return;
12696         }
12697         switch (vid.renderpath)
12698         {
12699         case RENDERPATH_GL20:
12700         case RENDERPATH_CGGL:
12701         case RENDERPATH_D3D9:
12702         case RENDERPATH_D3D10:
12703         case RENDERPATH_D3D11:
12704                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12705                 break;
12706         case RENDERPATH_GL13:
12707                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12708                 break;
12709         case RENDERPATH_GL11:
12710                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12711                 break;
12712         }
12713         CHECKGLERROR
12714 }
12715
12716 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12717 {
12718         int i, j;
12719         int texturenumsurfaces, endsurface;
12720         texture_t *texture;
12721         const msurface_t *surface;
12722 #define MAXBATCH_TRANSPARENTSURFACES 256
12723         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12724
12725         // if the model is static it doesn't matter what value we give for
12726         // wantnormals and wanttangents, so this logic uses only rules applicable
12727         // to a model, knowing that they are meaningless otherwise
12728         if (ent == r_refdef.scene.worldentity)
12729                 RSurf_ActiveWorldEntity();
12730         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12731                 RSurf_ActiveModelEntity(ent, false, false, false);
12732         else
12733         {
12734                 switch (vid.renderpath)
12735                 {
12736                 case RENDERPATH_GL20:
12737                 case RENDERPATH_CGGL:
12738                 case RENDERPATH_D3D9:
12739                 case RENDERPATH_D3D10:
12740                 case RENDERPATH_D3D11:
12741                         RSurf_ActiveModelEntity(ent, true, true, false);
12742                         break;
12743                 case RENDERPATH_GL13:
12744                 case RENDERPATH_GL11:
12745                         RSurf_ActiveModelEntity(ent, true, false, false);
12746                         break;
12747                 }
12748         }
12749
12750         if (r_transparentdepthmasking.integer)
12751         {
12752                 qboolean setup = false;
12753                 for (i = 0;i < numsurfaces;i = j)
12754                 {
12755                         j = i + 1;
12756                         surface = rsurface.modelsurfaces + surfacelist[i];
12757                         texture = surface->texture;
12758                         rsurface.texture = R_GetCurrentTexture(texture);
12759                         rsurface.lightmaptexture = NULL;
12760                         rsurface.deluxemaptexture = NULL;
12761                         rsurface.uselightmaptexture = false;
12762                         // scan ahead until we find a different texture
12763                         endsurface = min(i + 1024, numsurfaces);
12764                         texturenumsurfaces = 0;
12765                         texturesurfacelist[texturenumsurfaces++] = surface;
12766                         for (;j < endsurface;j++)
12767                         {
12768                                 surface = rsurface.modelsurfaces + surfacelist[j];
12769                                 if (texture != surface->texture)
12770                                         break;
12771                                 texturesurfacelist[texturenumsurfaces++] = surface;
12772                         }
12773                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12774                                 continue;
12775                         // render the range of surfaces as depth
12776                         if (!setup)
12777                         {
12778                                 setup = true;
12779                                 GL_ColorMask(0,0,0,0);
12780                                 GL_Color(1,1,1,1);
12781                                 GL_DepthTest(true);
12782                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12783                                 GL_DepthMask(true);
12784                                 GL_AlphaTest(false);
12785                                 R_Mesh_ResetTextureState();
12786                                 R_SetupShader_DepthOrShadow();
12787                         }
12788                         RSurf_SetupDepthAndCulling();
12789                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12790                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12791                         RSurf_DrawBatch();
12792                 }
12793                 if (setup)
12794                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12795         }
12796
12797         for (i = 0;i < numsurfaces;i = j)
12798         {
12799                 j = i + 1;
12800                 surface = rsurface.modelsurfaces + surfacelist[i];
12801                 texture = surface->texture;
12802                 rsurface.texture = R_GetCurrentTexture(texture);
12803                 rsurface.lightmaptexture = surface->lightmaptexture;
12804                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12805                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12806                 // scan ahead until we find a different texture
12807                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12808                 texturenumsurfaces = 0;
12809                 texturesurfacelist[texturenumsurfaces++] = surface;
12810                 for (;j < endsurface;j++)
12811                 {
12812                         surface = rsurface.modelsurfaces + surfacelist[j];
12813                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12814                                 break;
12815                         texturesurfacelist[texturenumsurfaces++] = surface;
12816                 }
12817                 // render the range of surfaces
12818                 if (ent == r_refdef.scene.worldentity)
12819                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12820                 else
12821                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12822         }
12823         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12824         GL_AlphaTest(false);
12825 }
12826
12827 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12828 {
12829         // transparent surfaces get pushed off into the transparent queue
12830         int surfacelistindex;
12831         const msurface_t *surface;
12832         vec3_t tempcenter, center;
12833         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12834         {
12835                 surface = texturesurfacelist[surfacelistindex];
12836                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12837                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12838                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12839                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12840                 if (queueentity->transparent_offset) // transparent offset
12841                 {
12842                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12843                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12844                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12845                 }
12846                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12847         }
12848 }
12849
12850 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12851 {
12852         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12853                 return;
12854         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12855                 return;
12856         RSurf_SetupDepthAndCulling();
12857         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12858         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12859         RSurf_DrawBatch();
12860 }
12861
12862 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12863 {
12864         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12865         CHECKGLERROR
12866         if (depthonly)
12867                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12868         else if (prepass)
12869         {
12870                 if (!rsurface.texture->currentnumlayers)
12871                         return;
12872                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12873                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12874                 else
12875                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12876         }
12877         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12878                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12879         else if (!rsurface.texture->currentnumlayers)
12880                 return;
12881         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12882         {
12883                 // in the deferred case, transparent surfaces were queued during prepass
12884                 if (!r_shadow_usingdeferredprepass)
12885                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12886         }
12887         else
12888         {
12889                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12890                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12891         }
12892         CHECKGLERROR
12893 }
12894
12895 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12896 {
12897         int i, j;
12898         texture_t *texture;
12899         // break the surface list down into batches by texture and use of lightmapping
12900         for (i = 0;i < numsurfaces;i = j)
12901         {
12902                 j = i + 1;
12903                 // texture is the base texture pointer, rsurface.texture is the
12904                 // current frame/skin the texture is directing us to use (for example
12905                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12906                 // use skin 1 instead)
12907                 texture = surfacelist[i]->texture;
12908                 rsurface.texture = R_GetCurrentTexture(texture);
12909                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12910                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12911                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12912                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12913                 {
12914                         // if this texture is not the kind we want, skip ahead to the next one
12915                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12916                                 ;
12917                         continue;
12918                 }
12919                 // simply scan ahead until we find a different texture or lightmap state
12920                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12921                         ;
12922                 // render the range of surfaces
12923                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12924         }
12925 }
12926
12927 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12928 {
12929         CHECKGLERROR
12930         if (depthonly)
12931                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12932         else if (prepass)
12933         {
12934                 if (!rsurface.texture->currentnumlayers)
12935                         return;
12936                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12937                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12938                 else
12939                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12940         }
12941         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12942                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12943         else if (!rsurface.texture->currentnumlayers)
12944                 return;
12945         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12946         {
12947                 // in the deferred case, transparent surfaces were queued during prepass
12948                 if (!r_shadow_usingdeferredprepass)
12949                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12950         }
12951         else
12952         {
12953                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12954                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12955         }
12956         CHECKGLERROR
12957 }
12958
12959 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12960 {
12961         int i, j;
12962         texture_t *texture;
12963         // break the surface list down into batches by texture and use of lightmapping
12964         for (i = 0;i < numsurfaces;i = j)
12965         {
12966                 j = i + 1;
12967                 // texture is the base texture pointer, rsurface.texture is the
12968                 // current frame/skin the texture is directing us to use (for example
12969                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12970                 // use skin 1 instead)
12971                 texture = surfacelist[i]->texture;
12972                 rsurface.texture = R_GetCurrentTexture(texture);
12973                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12974                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12975                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12976                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12977                 {
12978                         // if this texture is not the kind we want, skip ahead to the next one
12979                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12980                                 ;
12981                         continue;
12982                 }
12983                 // simply scan ahead until we find a different texture or lightmap state
12984                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12985                         ;
12986                 // render the range of surfaces
12987                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12988         }
12989 }
12990
12991 float locboxvertex3f[6*4*3] =
12992 {
12993         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12994         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12995         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12996         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12997         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12998         1,0,0, 0,0,0, 0,1,0, 1,1,0
12999 };
13000
13001 unsigned short locboxelements[6*2*3] =
13002 {
13003          0, 1, 2, 0, 2, 3,
13004          4, 5, 6, 4, 6, 7,
13005          8, 9,10, 8,10,11,
13006         12,13,14, 12,14,15,
13007         16,17,18, 16,18,19,
13008         20,21,22, 20,22,23
13009 };
13010
13011 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13012 {
13013         int i, j;
13014         cl_locnode_t *loc = (cl_locnode_t *)ent;
13015         vec3_t mins, size;
13016         float vertex3f[6*4*3];
13017         CHECKGLERROR
13018         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13019         GL_DepthMask(false);
13020         GL_DepthRange(0, 1);
13021         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13022         GL_DepthTest(true);
13023         GL_CullFace(GL_NONE);
13024         R_EntityMatrix(&identitymatrix);
13025
13026         R_Mesh_ResetTextureState();
13027
13028         i = surfacelist[0];
13029         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13030                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13031                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13032                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13033
13034         if (VectorCompare(loc->mins, loc->maxs))
13035         {
13036                 VectorSet(size, 2, 2, 2);
13037                 VectorMA(loc->mins, -0.5f, size, mins);
13038         }
13039         else
13040         {
13041                 VectorCopy(loc->mins, mins);
13042                 VectorSubtract(loc->maxs, loc->mins, size);
13043         }
13044
13045         for (i = 0;i < 6*4*3;)
13046                 for (j = 0;j < 3;j++, i++)
13047                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13048
13049         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13050         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13051         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13052 }
13053
13054 void R_DrawLocs(void)
13055 {
13056         int index;
13057         cl_locnode_t *loc, *nearestloc;
13058         vec3_t center;
13059         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13060         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13061         {
13062                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13063                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13064         }
13065 }
13066
13067 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13068 {
13069         if (decalsystem->decals)
13070                 Mem_Free(decalsystem->decals);
13071         memset(decalsystem, 0, sizeof(*decalsystem));
13072 }
13073
13074 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)
13075 {
13076         tridecal_t *decal;
13077         tridecal_t *decals;
13078         int i;
13079
13080         // expand or initialize the system
13081         if (decalsystem->maxdecals <= decalsystem->numdecals)
13082         {
13083                 decalsystem_t old = *decalsystem;
13084                 qboolean useshortelements;
13085                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13086                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13087                 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)));
13088                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13089                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13090                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13091                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13092                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13093                 if (decalsystem->numdecals)
13094                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13095                 if (old.decals)
13096                         Mem_Free(old.decals);
13097                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13098                         decalsystem->element3i[i] = i;
13099                 if (useshortelements)
13100                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13101                                 decalsystem->element3s[i] = i;
13102         }
13103
13104         // grab a decal and search for another free slot for the next one
13105         decals = decalsystem->decals;
13106         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13107         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13108                 ;
13109         decalsystem->freedecal = i;
13110         if (decalsystem->numdecals <= i)
13111                 decalsystem->numdecals = i + 1;
13112
13113         // initialize the decal
13114         decal->lived = 0;
13115         decal->triangleindex = triangleindex;
13116         decal->surfaceindex = surfaceindex;
13117         decal->decalsequence = decalsequence;
13118         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13119         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13120         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13121         decal->color4ub[0][3] = 255;
13122         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13123         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13124         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13125         decal->color4ub[1][3] = 255;
13126         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13127         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13128         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13129         decal->color4ub[2][3] = 255;
13130         decal->vertex3f[0][0] = v0[0];
13131         decal->vertex3f[0][1] = v0[1];
13132         decal->vertex3f[0][2] = v0[2];
13133         decal->vertex3f[1][0] = v1[0];
13134         decal->vertex3f[1][1] = v1[1];
13135         decal->vertex3f[1][2] = v1[2];
13136         decal->vertex3f[2][0] = v2[0];
13137         decal->vertex3f[2][1] = v2[1];
13138         decal->vertex3f[2][2] = v2[2];
13139         decal->texcoord2f[0][0] = t0[0];
13140         decal->texcoord2f[0][1] = t0[1];
13141         decal->texcoord2f[1][0] = t1[0];
13142         decal->texcoord2f[1][1] = t1[1];
13143         decal->texcoord2f[2][0] = t2[0];
13144         decal->texcoord2f[2][1] = t2[1];
13145 }
13146
13147 extern cvar_t cl_decals_bias;
13148 extern cvar_t cl_decals_models;
13149 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13150 // baseparms, parms, temps
13151 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)
13152 {
13153         int cornerindex;
13154         int index;
13155         float v[9][3];
13156         const float *vertex3f;
13157         int numpoints;
13158         float points[2][9][3];
13159         float temp[3];
13160         float tc[9][2];
13161         float f;
13162         float c[9][4];
13163         const int *e;
13164
13165         e = rsurface.modelelement3i + 3*triangleindex;
13166
13167         vertex3f = rsurface.modelvertex3f;
13168
13169         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13170         {
13171                 index = 3*e[cornerindex];
13172                 VectorCopy(vertex3f + index, v[cornerindex]);
13173         }
13174         // cull backfaces
13175         //TriangleNormal(v[0], v[1], v[2], normal);
13176         //if (DotProduct(normal, localnormal) < 0.0f)
13177         //      continue;
13178         // clip by each of the box planes formed from the projection matrix
13179         // if anything survives, we emit the decal
13180         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]);
13181         if (numpoints < 3)
13182                 return;
13183         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]);
13184         if (numpoints < 3)
13185                 return;
13186         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]);
13187         if (numpoints < 3)
13188                 return;
13189         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]);
13190         if (numpoints < 3)
13191                 return;
13192         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]);
13193         if (numpoints < 3)
13194                 return;
13195         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]);
13196         if (numpoints < 3)
13197                 return;
13198         // some part of the triangle survived, so we have to accept it...
13199         if (dynamic)
13200         {
13201                 // dynamic always uses the original triangle
13202                 numpoints = 3;
13203                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13204                 {
13205                         index = 3*e[cornerindex];
13206                         VectorCopy(vertex3f + index, v[cornerindex]);
13207                 }
13208         }
13209         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13210         {
13211                 // convert vertex positions to texcoords
13212                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13213                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13214                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13215                 // calculate distance fade from the projection origin
13216                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13217                 f = bound(0.0f, f, 1.0f);
13218                 c[cornerindex][0] = r * f;
13219                 c[cornerindex][1] = g * f;
13220                 c[cornerindex][2] = b * f;
13221                 c[cornerindex][3] = 1.0f;
13222                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13223         }
13224         if (dynamic)
13225                 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);
13226         else
13227                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13228                         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);
13229 }
13230 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)
13231 {
13232         matrix4x4_t projection;
13233         decalsystem_t *decalsystem;
13234         qboolean dynamic;
13235         dp_model_t *model;
13236         const msurface_t *surface;
13237         const msurface_t *surfaces;
13238         const int *surfacelist;
13239         const texture_t *texture;
13240         int numtriangles;
13241         int numsurfacelist;
13242         int surfacelistindex;
13243         int surfaceindex;
13244         int triangleindex;
13245         float localorigin[3];
13246         float localnormal[3];
13247         float localmins[3];
13248         float localmaxs[3];
13249         float localsize;
13250         //float normal[3];
13251         float planes[6][4];
13252         float angles[3];
13253         bih_t *bih;
13254         int bih_triangles_count;
13255         int bih_triangles[256];
13256         int bih_surfaces[256];
13257
13258         decalsystem = &ent->decalsystem;
13259         model = ent->model;
13260         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13261         {
13262                 R_DecalSystem_Reset(&ent->decalsystem);
13263                 return;
13264         }
13265
13266         if (!model->brush.data_leafs && !cl_decals_models.integer)
13267         {
13268                 if (decalsystem->model)
13269                         R_DecalSystem_Reset(decalsystem);
13270                 return;
13271         }
13272
13273         if (decalsystem->model != model)
13274                 R_DecalSystem_Reset(decalsystem);
13275         decalsystem->model = model;
13276
13277         RSurf_ActiveModelEntity(ent, false, false, false);
13278
13279         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13280         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13281         VectorNormalize(localnormal);
13282         localsize = worldsize*rsurface.inversematrixscale;
13283         localmins[0] = localorigin[0] - localsize;
13284         localmins[1] = localorigin[1] - localsize;
13285         localmins[2] = localorigin[2] - localsize;
13286         localmaxs[0] = localorigin[0] + localsize;
13287         localmaxs[1] = localorigin[1] + localsize;
13288         localmaxs[2] = localorigin[2] + localsize;
13289
13290         //VectorCopy(localnormal, planes[4]);
13291         //VectorVectors(planes[4], planes[2], planes[0]);
13292         AnglesFromVectors(angles, localnormal, NULL, false);
13293         AngleVectors(angles, planes[0], planes[2], planes[4]);
13294         VectorNegate(planes[0], planes[1]);
13295         VectorNegate(planes[2], planes[3]);
13296         VectorNegate(planes[4], planes[5]);
13297         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13298         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13299         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13300         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13301         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13302         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13303
13304 #if 1
13305 // works
13306 {
13307         matrix4x4_t forwardprojection;
13308         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13309         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13310 }
13311 #else
13312 // broken
13313 {
13314         float projectionvector[4][3];
13315         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13316         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13317         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13318         projectionvector[0][0] = planes[0][0] * ilocalsize;
13319         projectionvector[0][1] = planes[1][0] * ilocalsize;
13320         projectionvector[0][2] = planes[2][0] * ilocalsize;
13321         projectionvector[1][0] = planes[0][1] * ilocalsize;
13322         projectionvector[1][1] = planes[1][1] * ilocalsize;
13323         projectionvector[1][2] = planes[2][1] * ilocalsize;
13324         projectionvector[2][0] = planes[0][2] * ilocalsize;
13325         projectionvector[2][1] = planes[1][2] * ilocalsize;
13326         projectionvector[2][2] = planes[2][2] * ilocalsize;
13327         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13328         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13329         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13330         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13331 }
13332 #endif
13333
13334         dynamic = model->surfmesh.isanimated;
13335         numsurfacelist = model->nummodelsurfaces;
13336         surfacelist = model->sortedmodelsurfaces;
13337         surfaces = model->data_surfaces;
13338
13339         bih = NULL;
13340         bih_triangles_count = -1;
13341         if(!dynamic)
13342         {
13343                 if(model->render_bih.numleafs)
13344                         bih = &model->render_bih;
13345                 else if(model->collision_bih.numleafs)
13346                         bih = &model->collision_bih;
13347         }
13348         if(bih)
13349                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13350         if(bih_triangles_count == 0)
13351                 return;
13352         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13353                 return;
13354         if(bih_triangles_count > 0)
13355         {
13356                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13357                 {
13358                         surfaceindex = bih_surfaces[triangleindex];
13359                         surface = surfaces + surfaceindex;
13360                         texture = surface->texture;
13361                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13362                                 continue;
13363                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13364                                 continue;
13365                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13366                 }
13367         }
13368         else
13369         {
13370                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13371                 {
13372                         surfaceindex = surfacelist[surfacelistindex];
13373                         surface = surfaces + surfaceindex;
13374                         // check cull box first because it rejects more than any other check
13375                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13376                                 continue;
13377                         // skip transparent surfaces
13378                         texture = surface->texture;
13379                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13380                                 continue;
13381                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13382                                 continue;
13383                         numtriangles = surface->num_triangles;
13384                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13385                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13386                 }
13387         }
13388 }
13389
13390 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13391 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)
13392 {
13393         int renderentityindex;
13394         float worldmins[3];
13395         float worldmaxs[3];
13396         entity_render_t *ent;
13397
13398         if (!cl_decals_newsystem.integer)
13399                 return;
13400
13401         worldmins[0] = worldorigin[0] - worldsize;
13402         worldmins[1] = worldorigin[1] - worldsize;
13403         worldmins[2] = worldorigin[2] - worldsize;
13404         worldmaxs[0] = worldorigin[0] + worldsize;
13405         worldmaxs[1] = worldorigin[1] + worldsize;
13406         worldmaxs[2] = worldorigin[2] + worldsize;
13407
13408         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13409
13410         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13411         {
13412                 ent = r_refdef.scene.entities[renderentityindex];
13413                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13414                         continue;
13415
13416                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13417         }
13418 }
13419
13420 typedef struct r_decalsystem_splatqueue_s
13421 {
13422         vec3_t worldorigin;
13423         vec3_t worldnormal;
13424         float color[4];
13425         float tcrange[4];
13426         float worldsize;
13427         int decalsequence;
13428 }
13429 r_decalsystem_splatqueue_t;
13430
13431 int r_decalsystem_numqueued = 0;
13432 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13433
13434 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)
13435 {
13436         r_decalsystem_splatqueue_t *queue;
13437
13438         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13439                 return;
13440
13441         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13442         VectorCopy(worldorigin, queue->worldorigin);
13443         VectorCopy(worldnormal, queue->worldnormal);
13444         Vector4Set(queue->color, r, g, b, a);
13445         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13446         queue->worldsize = worldsize;
13447         queue->decalsequence = cl.decalsequence++;
13448 }
13449
13450 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13451 {
13452         int i;
13453         r_decalsystem_splatqueue_t *queue;
13454
13455         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13456                 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);
13457         r_decalsystem_numqueued = 0;
13458 }
13459
13460 extern cvar_t cl_decals_max;
13461 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13462 {
13463         int i;
13464         decalsystem_t *decalsystem = &ent->decalsystem;
13465         int numdecals;
13466         int killsequence;
13467         tridecal_t *decal;
13468         float frametime;
13469         float lifetime;
13470
13471         if (!decalsystem->numdecals)
13472                 return;
13473
13474         if (r_showsurfaces.integer)
13475                 return;
13476
13477         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13478         {
13479                 R_DecalSystem_Reset(decalsystem);
13480                 return;
13481         }
13482
13483         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13484         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13485
13486         if (decalsystem->lastupdatetime)
13487                 frametime = (cl.time - decalsystem->lastupdatetime);
13488         else
13489                 frametime = 0;
13490         decalsystem->lastupdatetime = cl.time;
13491         decal = decalsystem->decals;
13492         numdecals = decalsystem->numdecals;
13493
13494         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13495         {
13496                 if (decal->color4ub[0][3])
13497                 {
13498                         decal->lived += frametime;
13499                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13500                         {
13501                                 memset(decal, 0, sizeof(*decal));
13502                                 if (decalsystem->freedecal > i)
13503                                         decalsystem->freedecal = i;
13504                         }
13505                 }
13506         }
13507         decal = decalsystem->decals;
13508         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13509                 numdecals--;
13510
13511         // collapse the array by shuffling the tail decals into the gaps
13512         for (;;)
13513         {
13514                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13515                         decalsystem->freedecal++;
13516                 if (decalsystem->freedecal == numdecals)
13517                         break;
13518                 decal[decalsystem->freedecal] = decal[--numdecals];
13519         }
13520
13521         decalsystem->numdecals = numdecals;
13522
13523         if (numdecals <= 0)
13524         {
13525                 // if there are no decals left, reset decalsystem
13526                 R_DecalSystem_Reset(decalsystem);
13527         }
13528 }
13529
13530 extern skinframe_t *decalskinframe;
13531 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13532 {
13533         int i;
13534         decalsystem_t *decalsystem = &ent->decalsystem;
13535         int numdecals;
13536         tridecal_t *decal;
13537         float faderate;
13538         float alpha;
13539         float *v3f;
13540         float *c4f;
13541         float *t2f;
13542         const int *e;
13543         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13544         int numtris = 0;
13545
13546         numdecals = decalsystem->numdecals;
13547         if (!numdecals)
13548                 return;
13549
13550         if (r_showsurfaces.integer)
13551                 return;
13552
13553         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13554         {
13555                 R_DecalSystem_Reset(decalsystem);
13556                 return;
13557         }
13558
13559         // if the model is static it doesn't matter what value we give for
13560         // wantnormals and wanttangents, so this logic uses only rules applicable
13561         // to a model, knowing that they are meaningless otherwise
13562         if (ent == r_refdef.scene.worldentity)
13563                 RSurf_ActiveWorldEntity();
13564         else
13565                 RSurf_ActiveModelEntity(ent, false, false, false);
13566
13567         decalsystem->lastupdatetime = cl.time;
13568         decal = decalsystem->decals;
13569
13570         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13571
13572         // update vertex positions for animated models
13573         v3f = decalsystem->vertex3f;
13574         c4f = decalsystem->color4f;
13575         t2f = decalsystem->texcoord2f;
13576         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13577         {
13578                 if (!decal->color4ub[0][3])
13579                         continue;
13580
13581                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13582                         continue;
13583
13584                 // update color values for fading decals
13585                 if (decal->lived >= cl_decals_time.value)
13586                 {
13587                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13588                         alpha *= (1.0f/255.0f);
13589                 }
13590                 else
13591                         alpha = 1.0f/255.0f;
13592
13593                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13594                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13595                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13596                 c4f[ 3] = 1;
13597                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13598                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13599                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13600                 c4f[ 7] = 1;
13601                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13602                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13603                 c4f[10] = decal->color4ub[2][2] * alpha;
13604                 c4f[11] = 1;
13605
13606                 t2f[0] = decal->texcoord2f[0][0];
13607                 t2f[1] = decal->texcoord2f[0][1];
13608                 t2f[2] = decal->texcoord2f[1][0];
13609                 t2f[3] = decal->texcoord2f[1][1];
13610                 t2f[4] = decal->texcoord2f[2][0];
13611                 t2f[5] = decal->texcoord2f[2][1];
13612
13613                 // update vertex positions for animated models
13614                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13615                 {
13616                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13617                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13618                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13619                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13620                 }
13621                 else
13622                 {
13623                         VectorCopy(decal->vertex3f[0], v3f);
13624                         VectorCopy(decal->vertex3f[1], v3f + 3);
13625                         VectorCopy(decal->vertex3f[2], v3f + 6);
13626                 }
13627
13628                 if (r_refdef.fogenabled)
13629                 {
13630                         alpha = RSurf_FogVertex(v3f);
13631                         VectorScale(c4f, alpha, c4f);
13632                         alpha = RSurf_FogVertex(v3f + 3);
13633                         VectorScale(c4f + 4, alpha, c4f + 4);
13634                         alpha = RSurf_FogVertex(v3f + 6);
13635                         VectorScale(c4f + 8, alpha, c4f + 8);
13636                 }
13637
13638                 v3f += 9;
13639                 c4f += 12;
13640                 t2f += 6;
13641                 numtris++;
13642         }
13643
13644         if (numtris > 0)
13645         {
13646                 r_refdef.stats.drawndecals += numtris;
13647
13648                 // now render the decals all at once
13649                 // (this assumes they all use one particle font texture!)
13650                 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);
13651                 R_Mesh_ResetTextureState();
13652                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13653                 GL_DepthMask(false);
13654                 GL_DepthRange(0, 1);
13655                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13656                 GL_DepthTest(true);
13657                 GL_CullFace(GL_NONE);
13658                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13659                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13660                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13661         }
13662 }
13663
13664 static void R_DrawModelDecals(void)
13665 {
13666         int i, numdecals;
13667
13668         // fade faster when there are too many decals
13669         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13670         for (i = 0;i < r_refdef.scene.numentities;i++)
13671                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13672
13673         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13674         for (i = 0;i < r_refdef.scene.numentities;i++)
13675                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13676                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13677
13678         R_DecalSystem_ApplySplatEntitiesQueue();
13679
13680         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13681         for (i = 0;i < r_refdef.scene.numentities;i++)
13682                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13683
13684         r_refdef.stats.totaldecals += numdecals;
13685
13686         if (r_showsurfaces.integer)
13687                 return;
13688
13689         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13690
13691         for (i = 0;i < r_refdef.scene.numentities;i++)
13692         {
13693                 if (!r_refdef.viewcache.entityvisible[i])
13694                         continue;
13695                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13696                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13697         }
13698 }
13699
13700 extern cvar_t mod_collision_bih;
13701 void R_DrawDebugModel(void)
13702 {
13703         entity_render_t *ent = rsurface.entity;
13704         int i, j, k, l, flagsmask;
13705         const msurface_t *surface;
13706         dp_model_t *model = ent->model;
13707         vec3_t v;
13708
13709         switch(vid.renderpath)
13710         {
13711         case RENDERPATH_GL11:
13712         case RENDERPATH_GL13:
13713         case RENDERPATH_GL20:
13714         case RENDERPATH_CGGL:
13715                 break;
13716         case RENDERPATH_D3D9:
13717                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13718                 return;
13719         case RENDERPATH_D3D10:
13720                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13721                 return;
13722         case RENDERPATH_D3D11:
13723                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13724                 return;
13725         }
13726
13727         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13728
13729         R_Mesh_ResetTextureState();
13730         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13731         GL_DepthRange(0, 1);
13732         GL_DepthTest(!r_showdisabledepthtest.integer);
13733         GL_DepthMask(false);
13734         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13735
13736         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13737         {
13738                 int triangleindex;
13739                 int bihleafindex;
13740                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13741                 const q3mbrush_t *brush;
13742                 const bih_t *bih = &model->collision_bih;
13743                 const bih_leaf_t *bihleaf;
13744                 float vertex3f[3][3];
13745                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13746                 cullbox = false;
13747                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13748                 {
13749                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13750                                 continue;
13751                         switch (bihleaf->type)
13752                         {
13753                         case BIH_BRUSH:
13754                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13755                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13756                                 {
13757                                         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);
13758                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13759                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13760                                 }
13761                                 break;
13762                         case BIH_COLLISIONTRIANGLE:
13763                                 triangleindex = bihleaf->itemindex;
13764                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13765                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13766                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13767                                 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);
13768                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13769                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13770                                 break;
13771                         case BIH_RENDERTRIANGLE:
13772                                 triangleindex = bihleaf->itemindex;
13773                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13774                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13775                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13776                                 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);
13777                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13778                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13779                                 break;
13780                         }
13781                 }
13782         }
13783
13784         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13785
13786         if (r_showtris.integer || r_shownormals.integer)
13787         {
13788                 if (r_showdisabledepthtest.integer)
13789                 {
13790                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13791                         GL_DepthMask(false);
13792                 }
13793                 else
13794                 {
13795                         GL_BlendFunc(GL_ONE, GL_ZERO);
13796                         GL_DepthMask(true);
13797                 }
13798                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13799                 {
13800                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13801                                 continue;
13802                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13803                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13804                         {
13805                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13806                                 if (r_showtris.value > 0)
13807                                 {
13808                                         if (!rsurface.texture->currentlayers->depthmask)
13809                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13810                                         else if (ent == r_refdef.scene.worldentity)
13811                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13812                                         else
13813                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13814                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13815                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13816                                         RSurf_DrawBatch();
13817                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13818                                         CHECKGLERROR
13819                                 }
13820                                 if (r_shownormals.value < 0)
13821                                 {
13822                                         qglBegin(GL_LINES);
13823                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13824                                         {
13825                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13826                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13827                                                 qglVertex3f(v[0], v[1], v[2]);
13828                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13829                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13830                                                 qglVertex3f(v[0], v[1], v[2]);
13831                                         }
13832                                         qglEnd();
13833                                         CHECKGLERROR
13834                                 }
13835                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13836                                 {
13837                                         qglBegin(GL_LINES);
13838                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13839                                         {
13840                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13841                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13842                                                 qglVertex3f(v[0], v[1], v[2]);
13843                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13844                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13845                                                 qglVertex3f(v[0], v[1], v[2]);
13846                                         }
13847                                         qglEnd();
13848                                         CHECKGLERROR
13849                                         qglBegin(GL_LINES);
13850                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13851                                         {
13852                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13853                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13854                                                 qglVertex3f(v[0], v[1], v[2]);
13855                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13856                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13857                                                 qglVertex3f(v[0], v[1], v[2]);
13858                                         }
13859                                         qglEnd();
13860                                         CHECKGLERROR
13861                                         qglBegin(GL_LINES);
13862                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13863                                         {
13864                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13865                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13866                                                 qglVertex3f(v[0], v[1], v[2]);
13867                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13868                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13869                                                 qglVertex3f(v[0], v[1], v[2]);
13870                                         }
13871                                         qglEnd();
13872                                         CHECKGLERROR
13873                                 }
13874                         }
13875                 }
13876                 rsurface.texture = NULL;
13877         }
13878 }
13879
13880 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13881 int r_maxsurfacelist = 0;
13882 const msurface_t **r_surfacelist = NULL;
13883 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13884 {
13885         int i, j, endj, flagsmask;
13886         dp_model_t *model = r_refdef.scene.worldmodel;
13887         msurface_t *surfaces;
13888         unsigned char *update;
13889         int numsurfacelist = 0;
13890         if (model == NULL)
13891                 return;
13892
13893         if (r_maxsurfacelist < model->num_surfaces)
13894         {
13895                 r_maxsurfacelist = model->num_surfaces;
13896                 if (r_surfacelist)
13897                         Mem_Free((msurface_t**)r_surfacelist);
13898                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13899         }
13900
13901         RSurf_ActiveWorldEntity();
13902
13903         surfaces = model->data_surfaces;
13904         update = model->brushq1.lightmapupdateflags;
13905
13906         // update light styles on this submodel
13907         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13908         {
13909                 model_brush_lightstyleinfo_t *style;
13910                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13911                 {
13912                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13913                         {
13914                                 int *list = style->surfacelist;
13915                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13916                                 for (j = 0;j < style->numsurfaces;j++)
13917                                         update[list[j]] = true;
13918                         }
13919                 }
13920         }
13921
13922         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13923
13924         if (debug)
13925         {
13926                 R_DrawDebugModel();
13927                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13928                 return;
13929         }
13930
13931         rsurface.lightmaptexture = NULL;
13932         rsurface.deluxemaptexture = NULL;
13933         rsurface.uselightmaptexture = false;
13934         rsurface.texture = NULL;
13935         rsurface.rtlight = NULL;
13936         numsurfacelist = 0;
13937         // add visible surfaces to draw list
13938         for (i = 0;i < model->nummodelsurfaces;i++)
13939         {
13940                 j = model->sortedmodelsurfaces[i];
13941                 if (r_refdef.viewcache.world_surfacevisible[j])
13942                         r_surfacelist[numsurfacelist++] = surfaces + j;
13943         }
13944         // update lightmaps if needed
13945         if (model->brushq1.firstrender)
13946         {
13947                 model->brushq1.firstrender = false;
13948                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13949                         if (update[j])
13950                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13951         }
13952         else if (update)
13953         {
13954                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13955                         if (r_refdef.viewcache.world_surfacevisible[j])
13956                                 if (update[j])
13957                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13958         }
13959         // don't do anything if there were no surfaces
13960         if (!numsurfacelist)
13961         {
13962                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13963                 return;
13964         }
13965         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13966         GL_AlphaTest(false);
13967
13968         // add to stats if desired
13969         if (r_speeds.integer && !skysurfaces && !depthonly)
13970         {
13971                 r_refdef.stats.world_surfaces += numsurfacelist;
13972                 for (j = 0;j < numsurfacelist;j++)
13973                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13974         }
13975
13976         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13977 }
13978
13979 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13980 {
13981         int i, j, endj, flagsmask;
13982         dp_model_t *model = ent->model;
13983         msurface_t *surfaces;
13984         unsigned char *update;
13985         int numsurfacelist = 0;
13986         if (model == NULL)
13987                 return;
13988
13989         if (r_maxsurfacelist < model->num_surfaces)
13990         {
13991                 r_maxsurfacelist = model->num_surfaces;
13992                 if (r_surfacelist)
13993                         Mem_Free((msurface_t **)r_surfacelist);
13994                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13995         }
13996
13997         // if the model is static it doesn't matter what value we give for
13998         // wantnormals and wanttangents, so this logic uses only rules applicable
13999         // to a model, knowing that they are meaningless otherwise
14000         if (ent == r_refdef.scene.worldentity)
14001                 RSurf_ActiveWorldEntity();
14002         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14003                 RSurf_ActiveModelEntity(ent, false, false, false);
14004         else if (prepass)
14005                 RSurf_ActiveModelEntity(ent, true, true, true);
14006         else if (depthonly)
14007         {
14008                 switch (vid.renderpath)
14009                 {
14010                 case RENDERPATH_GL20:
14011                 case RENDERPATH_CGGL:
14012                 case RENDERPATH_D3D9:
14013                 case RENDERPATH_D3D10:
14014                 case RENDERPATH_D3D11:
14015                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14016                         break;
14017                 case RENDERPATH_GL13:
14018                 case RENDERPATH_GL11:
14019                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14020                         break;
14021                 }
14022         }
14023         else
14024         {
14025                 switch (vid.renderpath)
14026                 {
14027                 case RENDERPATH_GL20:
14028                 case RENDERPATH_CGGL:
14029                 case RENDERPATH_D3D9:
14030                 case RENDERPATH_D3D10:
14031                 case RENDERPATH_D3D11:
14032                         RSurf_ActiveModelEntity(ent, true, true, false);
14033                         break;
14034                 case RENDERPATH_GL13:
14035                 case RENDERPATH_GL11:
14036                         RSurf_ActiveModelEntity(ent, true, false, false);
14037                         break;
14038                 }
14039         }
14040
14041         surfaces = model->data_surfaces;
14042         update = model->brushq1.lightmapupdateflags;
14043
14044         // update light styles
14045         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14046         {
14047                 model_brush_lightstyleinfo_t *style;
14048                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14049                 {
14050                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14051                         {
14052                                 int *list = style->surfacelist;
14053                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14054                                 for (j = 0;j < style->numsurfaces;j++)
14055                                         update[list[j]] = true;
14056                         }
14057                 }
14058         }
14059
14060         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14061
14062         if (debug)
14063         {
14064                 R_DrawDebugModel();
14065                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14066                 return;
14067         }
14068
14069         rsurface.lightmaptexture = NULL;
14070         rsurface.deluxemaptexture = NULL;
14071         rsurface.uselightmaptexture = false;
14072         rsurface.texture = NULL;
14073         rsurface.rtlight = NULL;
14074         numsurfacelist = 0;
14075         // add visible surfaces to draw list
14076         for (i = 0;i < model->nummodelsurfaces;i++)
14077                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14078         // don't do anything if there were no surfaces
14079         if (!numsurfacelist)
14080         {
14081                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14082                 return;
14083         }
14084         // update lightmaps if needed
14085         if (update)
14086         {
14087                 int updated = 0;
14088                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14089                 {
14090                         if (update[j])
14091                         {
14092                                 updated++;
14093                                 R_BuildLightMap(ent, surfaces + j);
14094                         }
14095                 }
14096         }
14097         if (update)
14098                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14099                         if (update[j])
14100                                 R_BuildLightMap(ent, surfaces + j);
14101         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14102         GL_AlphaTest(false);
14103
14104         // add to stats if desired
14105         if (r_speeds.integer && !skysurfaces && !depthonly)
14106         {
14107                 r_refdef.stats.entities_surfaces += numsurfacelist;
14108                 for (j = 0;j < numsurfacelist;j++)
14109                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14110         }
14111
14112         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14113 }
14114
14115 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14116 {
14117         static texture_t texture;
14118         static msurface_t surface;
14119         const msurface_t *surfacelist = &surface;
14120
14121         // fake enough texture and surface state to render this geometry
14122
14123         texture.update_lastrenderframe = -1; // regenerate this texture
14124         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14125         texture.currentskinframe = skinframe;
14126         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14127         texture.offsetmapping = OFFSETMAPPING_OFF;
14128         texture.offsetscale = 1;
14129         texture.specularscalemod = 1;
14130         texture.specularpowermod = 1;
14131
14132         surface.texture = &texture;
14133         surface.num_triangles = numtriangles;
14134         surface.num_firsttriangle = firsttriangle;
14135         surface.num_vertices = numvertices;
14136         surface.num_firstvertex = firstvertex;
14137
14138         // now render it
14139         rsurface.texture = R_GetCurrentTexture(surface.texture);
14140         rsurface.lightmaptexture = NULL;
14141         rsurface.deluxemaptexture = NULL;
14142         rsurface.uselightmaptexture = false;
14143         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14144 }
14145
14146 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)
14147 {
14148         static msurface_t surface;
14149         const msurface_t *surfacelist = &surface;
14150
14151         // fake enough texture and surface state to render this geometry
14152
14153         surface.texture = texture;
14154         surface.num_triangles = numtriangles;
14155         surface.num_firsttriangle = firsttriangle;
14156         surface.num_vertices = numvertices;
14157         surface.num_firstvertex = firstvertex;
14158
14159         // now render it
14160         rsurface.texture = R_GetCurrentTexture(surface.texture);
14161         rsurface.lightmaptexture = NULL;
14162         rsurface.deluxemaptexture = NULL;
14163         rsurface.uselightmaptexture = false;
14164         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14165 }