]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
cs_*project: as both 2D and 3D rendering are confined to the viewport, it SHOULD...
[xonotic/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 | TEXF_ALLOWUPDATES, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, 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 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
592 "#endif\n"
593 "\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "#   extension GL_EXT_gpu_shader4 : enable\n"
597 "# endif\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "#   extension GL_ARB_texture_gather : enable\n"
600 "# else\n"
601 "#   ifdef GL_AMD_texture_texture4\n"
602 "#     extension GL_AMD_texture_texture4 : enable\n"
603 "#   endif\n"
604 "# endif\n"
605 "#endif\n"
606 "\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
609 "#endif\n"
610 "\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
613 "//#endif\n"
614 "\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
620 "//#else\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
625 "//#endif\n"
626 "\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#endif\n"
630 "\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "}\n"
637 "#endif\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
639 "\n"
640 "\n"
641 "\n"
642 "\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
649 "}\n"
650 "#endif\n"
651 "\n"
652 "#ifdef FRAGMENT_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_FragColor = gl_Color;\n"
656 "}\n"
657 "#endif\n"
658 "#else // !MODE_SHOWDEPTH\n"
659 "\n"
660 "\n"
661 "\n"
662 "\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
666 "\n"
667 "#ifdef VERTEX_SHADER\n"
668 "void main(void)\n"
669 "{\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 "#ifdef USEBLOOM\n"
673 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
674 "#endif\n"
675 "}\n"
676 "#endif\n"
677 "\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
680 "#ifdef USEBLOOM\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
683 "#endif\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
686 "#endif\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
692 "#endif\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
700 "void main(void)\n"
701 "{\n"
702 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 "#ifdef USEBLOOM\n"
704 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#endif\n"
706 "#ifdef USEVIEWTINT\n"
707 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// 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"
713 "       float sobel = 1.0;\n"
714 "       // vec2 ts = textureSize(Texture_First, 0);\n"
715 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 "       vec2 px = PixelSize;\n"
717 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
719 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
722 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
725 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
728 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#endif\n"
750 "\n"
751 "#ifdef USESATURATION\n"
752 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#endif\n"
757 "\n"
758 "#ifdef USEGAMMARAMPS\n"
759 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
762 "#endif\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_POSTPROCESS\n"
766 "\n"
767 "\n"
768 "\n"
769 "\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
773 "#endif\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
776 "#endif\n"
777 "#ifdef VERTEX_SHADER\n"
778 "void main(void)\n"
779 "{\n"
780 "       gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
783 "#endif\n"
784 "#ifdef USESPECULAR\n"
785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
786 "#endif\n"
787 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
788 "}\n"
789 "#endif\n"
790 "\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
797 "#endif\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#endif\n"
805 "\n"
806 "#ifdef USESPECULAR\n"
807 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 "       gl_FragColor *= tex2;\n"
810 "# endif\n"
811 "# ifdef USEGLOW\n"
812 "       gl_FragColor += tex2;\n"
813 "# endif\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
816 "# endif\n"
817 "#endif\n"
818 "}\n"
819 "#endif\n"
820 "#else // !MODE_GENERIC\n"
821 "\n"
822 "\n"
823 "\n"
824 "\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
828 "void main(void)\n"
829 "{\n"
830 "       gl_FrontColor = gl_Color;\n"
831 "       TexCoord = gl_MultiTexCoord0.xy;\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "}\n"
834 "#endif\n"
835 "\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
839 "\n"
840 "void main(void)\n"
841 "{\n"
842 "       int i;\n"
843 "       vec2 tc = TexCoord;\n"
844 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 "       tc += BloomBlur_Parameters.xy;\n"
846 "       for (i = 1;i < SAMPLES;i++)\n"
847 "       {\n"
848 "               color += texture2D(Texture_First, tc).rgb;\n"
849 "               tc += BloomBlur_Parameters.xy;\n"
850 "       }\n"
851 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
860 "\n"
861 "void main(void)\n"
862 "{\n"
863 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 "       ModelViewProjectionPosition = gl_Position;\n"
866 "}\n"
867 "#endif\n"
868 "\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
873 "\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 "       // FIXME temporary hack to detect the case that the reflection\n"
889 "       // gets blackened at edges due to leaving the area that contains actual\n"
890 "       // content.\n"
891 "       // Remove this 'ack once we have a better way to stop this thing from\n"
892 "       // 'appening.\n"
893 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
899 "}\n"
900 "#endif\n"
901 "#else // !MODE_REFRACTION\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
913 "\n"
914 "void main(void)\n"
915 "{\n"
916 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 "       ModelViewProjectionPosition = gl_Position;\n"
923 "}\n"
924 "#endif\n"
925 "\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
930 "\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
938 "\n"
939 "void main(void)\n"
940 "{\n"
941 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 "       // FIXME temporary hack to detect the case that the reflection\n"
947 "       // gets blackened at edges due to leaving the area that contains actual\n"
948 "       // content.\n"
949 "       // Remove this 'ack once we have a better way to stop this thing from\n"
950 "       // 'appening.\n"
951 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
963 "}\n"
964 "#endif\n"
965 "#else // !MODE_WATER\n"
966 "\n"
967 "\n"
968 "\n"
969 "\n"
970 "// common definitions between vertex shader and fragment shader:\n"
971 "\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
975 "#endif\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
982 "#endif\n"
983 "\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
986 "#endif\n"
987 "\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
990 "#endif\n"
991 "#ifdef USEFOG\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
993 "#endif\n"
994 "\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1003 "#endif\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1011 "#endif\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1015 "#endif\n"
1016 "uniform vec4 FogPlane;\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1020 "#endif\n"
1021 "\n"
1022 "\n"
1023 "\n"
1024 "\n"
1025 "\n"
1026 "// 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"
1027 "\n"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1030 "\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1034 "#ifdef USEGLOW\n"
1035 "uniform sampler2D Texture_Glow;\n"
1036 "#endif\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1041 "#ifdef USEGLOW\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1043 "#endif\n"
1044 "#endif\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1048 "#endif\n"
1049 "#ifdef USEFOG\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1052 "#endif\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1054 "#endif\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1057 "#endif\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1060 "#endif\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1068 "#endif\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1072 "#endif\n"
1073 "\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1077 "\n"
1078 "#ifdef USEFOG\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1083 "{\n"
1084 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1086 "       float fogfrac;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 "       fogfrac = fogheightpixel.a;\n"
1090 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1091 "#else\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1094 "# else\n"
1095 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1096 "# endif\n"
1097 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1098 "#endif\n"
1099 "}\n"
1100 "#endif\n"
1101 "\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1105 "{\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 "       // 14 sample relief mapping: linear search and then binary search\n"
1108 "       // this basically steps forward a small amount repeatedly until it finds\n"
1109 "       // itself inside solid, then jitters forward and back using decreasing\n"
1110 "       // amounts to find the impact\n"
1111 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 "       vec3 RT = vec3(TexCoord, 1);\n"
1115 "       OffsetVector *= 0.1;\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);\n"
1118 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1126 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1127 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1128 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1130 "       return RT.xy;\n"
1131 "#else\n"
1132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 "       // this basically moves forward the full distance, and then backs up based\n"
1134 "       // on height of samples\n"
1135 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 "       TexCoord += OffsetVector;\n"
1139 "       OffsetVector *= 0.333;\n"
1140 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 "       return TexCoord;\n"
1144 "#endif\n"
1145 "}\n"
1146 "#endif // USEOFFSETMAPPING\n"
1147 "\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1151 "#endif\n"
1152 "\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1158 "# else\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1160 "# endif\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1166 "# else\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1168 "# endif\n"
1169 "#endif\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1178 "# else\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1180 "# endif\n"
1181 "#endif\n"
1182 "\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1186 "#endif\n"
1187 "\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1191 "# else\n"
1192 "#  ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1194 "{\n"
1195 "       vec3 adir = abs(dir);\n"
1196 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1199 "}\n"
1200 "#  else\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       float ma = adir.z;\n"
1205 "       vec4 proj = vec4(dir, 2.5);\n"
1206 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 "       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"
1210 "}\n"
1211 "#  endif\n"
1212 "# endif\n"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1217 "{\n"
1218 "       vec3 adir = abs(dir);\n"
1219 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1220 "}\n"
1221 "#endif\n"
1222 "\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1225 "{\n"
1226 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "       float f;\n"
1228 "#  ifdef USESHADOWSAMPLER\n"
1229 "\n"
1230 "#    ifdef USESHADOWMAPPCF\n"
1231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 "       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"
1233 "#    else\n"
1234 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1235 "#    endif\n"
1236 "\n"
1237 "#  else\n"
1238 "\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 "       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"
1244 "       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"
1245 "       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"
1246 "       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"
1247 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1249 "#      else\n"
1250 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 "       vec2 offset = fract(shadowmaptc.xy);\n"
1252 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1254 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1255 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1257 "#      endif\n"
1258 "#    else\n"
1259 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1260 "#    endif\n"
1261 "\n"
1262 "#  endif\n"
1263 "#  ifdef USESHADOWMAPORTHO\n"
1264 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1265 "#  else\n"
1266 "       return f;\n"
1267 "#  endif\n"
1268 "}\n"
1269 "# endif\n"
1270 "\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1273 "{\n"
1274 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1275 "       float f;\n"
1276 "\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "#    ifdef USESHADOWMAPPCF\n"
1279 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1280 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 "       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"
1282 "#    else\n"
1283 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1284 "#    endif\n"
1285 "#  else\n"
1286 "#    ifdef USESHADOWMAPPCF\n"
1287 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "#      ifdef GL_ARB_texture_gather\n"
1289 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1290 "#      else\n"
1291 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1292 "#      endif\n"
1293 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "#      if USESHADOWMAPPCF > 1\n"
1295 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1299 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1300 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1301 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1302 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1303 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1304 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 "       locols.yz += group2.ab;\n"
1307 "       hicols.yz += group8.rg;\n"
1308 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 "                               mix(locols, hicols, offset.y);\n"
1311 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 "       f = dot(cols, vec4(1.0/25.0));\n"
1314 "#      else\n"
1315 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1318 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1319 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1322 "#      endif\n"
1323 "#     else\n"
1324 "#      ifdef GL_EXT_gpu_shader4\n"
1325 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1326 "#      else\n"
1327 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1328 "#      endif\n"
1329 "#      if USESHADOWMAPPCF > 1\n"
1330 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 "       center *= ShadowMap_TextureScale;\n"
1332 "       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"
1333 "       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"
1334 "       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"
1335 "       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"
1336 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      else\n"
1339 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1342 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1343 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1345 "#      endif\n"
1346 "#     endif\n"
1347 "#    else\n"
1348 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1349 "#    endif\n"
1350 "#  endif\n"
1351 "#  ifdef USESHADOWMAPORTHO\n"
1352 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1353 "#  else\n"
1354 "       return f;\n"
1355 "#  endif\n"
1356 "}\n"
1357 "# endif\n"
1358 "\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1361 "{\n"
1362 "       // apply depth texture cubemap as light filter\n"
1363 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1364 "       float f;\n"
1365 "#  ifdef USESHADOWSAMPLER\n"
1366 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1367 "#  else\n"
1368 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1369 "#  endif\n"
1370 "       return f;\n"
1371 "}\n"
1372 "# endif\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#endif\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1386 "void main(void)\n"
1387 "{\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#endif\n"
1393 "\n"
1394 "       // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1400 "#endif\n"
1401 "\n"
1402 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "void main(void)\n"
1411 "{\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 "       // apply offsetmapping\n"
1414 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1416 "#endif\n"
1417 "\n"
1418 "#ifdef USEALPHAKILL\n"
1419 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1420 "               discard;\n"
1421 "#endif\n"
1422 "\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1433 "#else\n"
1434 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1436 "#endif\n"
1437 "\n"
1438 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1439 "}\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1442 "\n"
1443 "\n"
1444 "\n"
1445 "\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1449 "void main(void)\n"
1450 "{\n"
1451 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1465 "#endif\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1467 "void main(void)\n"
1468 "{\n"
1469 "       // calculate viewspace pixel position\n"
1470 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1471 "       vec3 position;\n"
1472 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 "       // decode viewspace pixel normal\n"
1475 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 "       // surfacenormal = pixel normal in viewspace\n"
1478 "       // LightVector = pixel to light in viewspace\n"
1479 "       // CubeVector = position in lightspace\n"
1480 "       // eyevector = pixel to view in viewspace\n"
1481 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 "       // calculate diffuse shading\n"
1485 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1487 "#endif\n"
1488 "#ifdef USESPECULAR\n"
1489 "       // calculate directional shading\n"
1490 "       vec3 eyevector = position * -1.0;\n"
1491 "#  ifdef USEEXACTSPECULARMATH\n"
1492 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1493 "#  else\n"
1494 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1496 "#  endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 "       fade *= ShadowMapCompare(CubeVector);\n"
1501 "#endif\n"
1502 "\n"
1503 "#ifdef USEDIFFUSE\n"
1504 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1505 "#else\n"
1506 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1507 "#endif\n"
1508 "#ifdef USESPECULAR\n"
1509 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1510 "#else\n"
1511 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1512 "#endif\n"
1513 "\n"
1514 "# ifdef USECUBEFILTER\n"
1515 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 "       gl_FragData[0].rgb *= cubecolor;\n"
1517 "       gl_FragData[1].rgb *= cubecolor;\n"
1518 "# endif\n"
1519 "}\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1522 "\n"
1523 "\n"
1524 "\n"
1525 "\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1530 "#endif\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1533 "#endif\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1536 "#endif\n"
1537 "void main(void)\n"
1538 "{\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 "       gl_FrontColor = gl_Color;\n"
1541 "#endif\n"
1542 "       // copy the surface texcoord\n"
1543 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1546 "#endif\n"
1547 "#ifdef USELIGHTMAP\n"
1548 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1549 "#endif\n"
1550 "\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 "       // transform vertex position into light attenuation/cubemap space\n"
1553 "       // (-1 to +1 across the light box)\n"
1554 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1555 "\n"
1556 "# ifdef USEDIFFUSE\n"
1557 "       // transform unnormalized light direction into tangent space\n"
1558 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 "       //  normalize it per pixel)\n"
1560 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1564 "# endif\n"
1565 "#endif\n"
1566 "\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1571 "#endif\n"
1572 "\n"
1573 "       // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1579 "#endif\n"
1580 "\n"
1581 "#ifdef USEFOG\n"
1582 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1584 "#endif\n"
1585 "\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1588 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1589 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1590 "#endif\n"
1591 "\n"
1592 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1594 "\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1597 "#endif\n"
1598 "\n"
1599 "#ifdef USEREFLECTION\n"
1600 "       ModelViewProjectionPosition = gl_Position;\n"
1601 "#endif\n"
1602 "}\n"
1603 "#endif // VERTEX_SHADER\n"
1604 "\n"
1605 "\n"
1606 "\n"
1607 "\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1613 "#endif\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1618 "#ifdef USEGLOW\n"
1619 "uniform myhalf3 Color_Glow;\n"
1620 "#endif\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1627 "#endif\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1632 "#endif\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1635 "#endif\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1638 "#endif\n"
1639 "void main(void)\n"
1640 "{\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 "       // apply offsetmapping\n"
1643 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1645 "#endif\n"
1646 "\n"
1647 "       // combine the diffuse textures (base, pants, shirt)\n"
1648 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 "       if (color.a < 0.5)\n"
1651 "               discard;\n"
1652 "#endif\n"
1653 "       color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1656 "#endif\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1662 "       color.a = 1.0;\n"
1663 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1664 "#endif\n"
1665 "\n"
1666 "       // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1669 "#else\n"
1670 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1671 "#endif\n"
1672 "\n"
1673 "       // get the material colors\n"
1674 "       myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1678 "# else\n"
1679 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1680 "# endif\n"
1681 "#endif\n"
1682 "\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1702 "#else\n"
1703 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1705 "#endif\n"
1706 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1707 "#endif\n"
1708 "#else\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif\n"
1711 "       color.rgb *= LightColor;\n"
1712 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1715 "#endif\n"
1716 "# ifdef USECUBEFILTER\n"
1717 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1718 "# endif\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1725 "#define SHADING\n"
1726 "#ifdef USEDIFFUSE\n"
1727 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1728 "#endif\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "       // convert modelspace light vector to tangentspace\n"
1737 "       myhalf3 lightnormal;\n"
1738 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1753 "#define SHADING\n"
1754 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1757 "#endif\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 "       color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef SHADING\n"
1776 "# ifdef USEDIFFUSE\n"
1777 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "#  ifdef USESPECULAR\n"
1779 "#   ifdef USEEXACTSPECULARMATH\n"
1780 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1781 "#   else\n"
1782 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1784 "#   endif\n"
1785 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1786 "#  else\n"
1787 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1788 "#  endif\n"
1789 "# else\n"
1790 "       color.rgb = diffusetex * Color_Ambient;\n"
1791 "# endif\n"
1792 "#endif\n"
1793 "\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEGLOW\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1807 "#else\n"
1808 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1809 "#endif\n"
1810 "#endif\n"
1811 "\n"
1812 "#ifdef USEFOG\n"
1813 "       color.rgb = FogVertex(color.rgb);\n"
1814 "#endif\n"
1815 "\n"
1816 "       // 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"
1817 "#ifdef USEREFLECTION\n"
1818 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 "       // FIXME temporary hack to detect the case that the reflection\n"
1823 "       // gets blackened at edges due to leaving the area that contains actual\n"
1824 "       // content.\n"
1825 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1826 "       // 'appening.\n"
1827 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1833 "#endif\n"
1834 "\n"
1835 "       gl_FragColor = vec4(color);\n"
1836 "}\n"
1837 "#endif // FRAGMENT_SHADER\n"
1838 "\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1848 ;
1849
1850 /*
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868
1869
1870
1871 =========================================================================================================================================================
1872
1873
1874
1875 =========================================================================================================================================================
1876 */
1877
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1882 "\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1886 "#endif\n"
1887 "\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1889 "# define USEFOG\n"
1890 "#endif\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1893 "#endif\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "#ifdef HLSL\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1903 "#else\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1905 "#endif\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1916 ")\n"
1917 "{\n"
1918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 "       Depth = gl_Position.z;\n"
1920 "}\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1928 ")\n"
1929 "{\n"
1930 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 "       temp.yz -= floor(temp.yz);\n"
1933 "       gl_FragColor = float4(temp,0);\n"
1934 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1935 "}\n"
1936 "#endif\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "       gl_FragColor = gl_FrontColor;\n"
1965 "}\n"
1966 "#endif\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1973 "\n"
1974 "#ifdef VERTEX_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 "#ifdef USEBLOOM\n"
1989 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1990 "#endif\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2000 "#ifdef USEBLOOM\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2002 "#endif\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2005 "#endif\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2008 "#endif\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2011 "#endif\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2020 ")\n"
2021 "{\n"
2022 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2023 "#ifdef USEBLOOM\n"
2024 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// 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"
2033 "       float sobel = 1.0;\n"
2034 "       // float2 ts = textureSize(Texture_First, 0);\n"
2035 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 "       float2 px = PixelSize;\n"
2037 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2039 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2042 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2045 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2048 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2066 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2067 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef USESATURATION\n"
2072 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2103 ")\n"
2104 "{\n"
2105 "#ifdef HLSL\n"
2106 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2107 "#else\n"
2108 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2109 "#endif\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "       gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef USESPECULAR\n"
2142 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 "       gl_FragColor *= tex2;\n"
2145 "# endif\n"
2146 "# ifdef USEGLOW\n"
2147 "       gl_FragColor += tex2;\n"
2148 "# endif\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2151 "# endif\n"
2152 "#endif\n"
2153 "}\n"
2154 "#endif\n"
2155 "#else // !MODE_GENERIC\n"
2156 "\n"
2157 "\n"
2158 "\n"
2159 "\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2162 "void main\n"
2163 "(\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2169 ")\n"
2170 "{\n"
2171 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2172 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "\n"
2178 "void main\n"
2179 "(\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2184 ")\n"
2185 "{\n"
2186 "       int i;\n"
2187 "       float2 tc = TexCoord;\n"
2188 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 "       tc += BloomBlur_Parameters.xy;\n"
2190 "       for (i = 1;i < SAMPLES;i++)\n"
2191 "       {\n"
2192 "               color += tex2D(Texture_First, tc).rgb;\n"
2193 "               tc += BloomBlur_Parameters.xy;\n"
2194 "       }\n"
2195 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2196 "}\n"
2197 "#endif\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2201 "void main\n"
2202 "(\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2212 ")\n"
2213 "{\n"
2214 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 "       ModelViewProjectionPosition = gl_Position;\n"
2217 "}\n"
2218 "#endif\n"
2219 "\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2221 "void main\n"
2222 "(\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 "       //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"
2238 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 "       // FIXME temporary hack to detect the case that the reflection\n"
2241 "       // gets blackened at edges due to leaving the area that contains actual\n"
2242 "       // content.\n"
2243 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2244 "       // 'appening.\n"
2245 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_REFRACTION\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2260 "\n"
2261 "void main\n"
2262 "(\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2275 ")\n"
2276 "{\n"
2277 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 "       ModelViewProjectionPosition = gl_Position;\n"
2284 "}\n"
2285 "#endif\n"
2286 "\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2288 "void main\n"
2289 "(\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2304 ")\n"
2305 "{\n"
2306 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xyxy * DistortScaleRefractReflect;\n"
2311 "       // FIXME temporary hack to detect the case that the reflection\n"
2312 "       // gets blackened at edges due to leaving the area that contains actual\n"
2313 "       // content.\n"
2314 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2315 "       // 'appening.\n"
2316 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2328 "}\n"
2329 "#endif\n"
2330 "#else // !MODE_WATER\n"
2331 "\n"
2332 "\n"
2333 "\n"
2334 "\n"
2335 "// 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"
2336 "\n"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2339 "\n"
2340 "#ifdef USEFOG\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2342 "{\n"
2343 "       float fogfrac;\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 "       fogfrac = fogheightpixel.a;\n"
2347 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2348 "#else\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2351 "# else\n"
2352 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2353 "# endif\n"
2354 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2355 "#endif\n"
2356 "}\n"
2357 "#endif\n"
2358 "\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2361 "{\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 "       // 14 sample relief mapping: linear search and then binary search\n"
2364 "       // this basically steps forward a small amount repeatedly until it finds\n"
2365 "       // itself inside solid, then jitters forward and back using decreasing\n"
2366 "       // amounts to find the impact\n"
2367 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 "       float3 RT = float3(TexCoord, 1);\n"
2371 "       OffsetVector *= 0.1;\n"
2372 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2382 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2383 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2384 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2386 "       return RT.xy;\n"
2387 "#else\n"
2388 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 "       // this basically moves forward the full distance, and then backs up based\n"
2390 "       // on height of samples\n"
2391 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 "       TexCoord += OffsetVector;\n"
2395 "       OffsetVector *= 0.333;\n"
2396 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       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"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       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"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2438 "{\n"
2439 "       float3 adir = abs(dir);\n"
2440 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2441 "}\n"
2442 "#endif\n"
2443 "\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2447 "#else\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2449 "#endif\n"
2450 "{\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2453 "#else\n"
2454 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2455 "#endif\n"
2456 "       float f;\n"
2457 "#  ifdef USESHADOWSAMPLER\n"
2458 "\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 "       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"
2462 "#    else\n"
2463 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2464 "#    endif\n"
2465 "\n"
2466 "#  else\n"
2467 "\n"
2468 "#    ifdef USESHADOWMAPPCF\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 "       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"
2473 "       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"
2474 "       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"
2475 "       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"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 "       float2 offset = frac(shadowmaptc.xy);\n"
2481 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2483 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2484 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2486 "#      endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2489 "#    endif\n"
2490 "\n"
2491 "#  endif\n"
2492 "#  ifdef USESHADOWMAPORTHO\n"
2493 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2494 "#  else\n"
2495 "       return f;\n"
2496 "#  endif\n"
2497 "}\n"
2498 "# endif\n"
2499 "\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2503 "#else\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2505 "#endif\n"
2506 "{\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2509 "#else\n"
2510 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2511 "#endif\n"
2512 "       float f;\n"
2513 "\n"
2514 "#  ifdef USESHADOWSAMPLER\n"
2515 "#    ifdef USESHADOWMAPPCF\n"
2516 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2517 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 "       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"
2519 "#    else\n"
2520 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2521 "#    endif\n"
2522 "#  else\n"
2523 "#    ifdef USESHADOWMAPPCF\n"
2524 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "#      ifdef GL_ARB_texture_gather\n"
2526 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2529 "#      endif\n"
2530 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "#      if USESHADOWMAPPCF > 1\n"
2532 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2536 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2537 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2538 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2539 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2540 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2541 "       float4 locols = float4(group1.ab, group3.ab);\n"
2542 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2543 "       locols.yz += group2.ab;\n"
2544 "       hicols.yz += group8.rg;\n"
2545 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 "                               lerp(locols, hicols, offset.y);\n"
2548 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 "       f = dot(cols, float4(1.0/25.0));\n"
2551 "#      else\n"
2552 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2555 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2556 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2559 "#      endif\n"
2560 "#     else\n"
2561 "#      ifdef GL_EXT_gpu_shader4\n"
2562 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2563 "#      else\n"
2564 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2565 "#      endif\n"
2566 "#      if USESHADOWMAPPCF > 1\n"
2567 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 "       center *= ShadowMap_TextureScale;\n"
2569 "       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"
2570 "       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"
2571 "       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"
2572 "       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"
2573 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2575 "#      else\n"
2576 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2579 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2580 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2582 "#      endif\n"
2583 "#     endif\n"
2584 "#    else\n"
2585 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2586 "#    endif\n"
2587 "#  endif\n"
2588 "#  ifdef USESHADOWMAPORTHO\n"
2589 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2590 "#  else\n"
2591 "       return f;\n"
2592 "#  endif\n"
2593 "}\n"
2594 "# endif\n"
2595 "\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2598 "{\n"
2599 "       // apply depth texture cubemap as light filter\n"
2600 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2601 "       float f;\n"
2602 "#  ifdef USESHADOWSAMPLER\n"
2603 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2604 "#  else\n"
2605 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2606 "#  endif\n"
2607 "       return f;\n"
2608 "}\n"
2609 "# endif\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\n"
2617 "#ifdef VERTEX_SHADER\n"
2618 "void main\n"
2619 "(\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2624 "#endif\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2632 "#endif\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2636 "#endif\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#endif\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2646 ")\n"
2647 "{\n"
2648 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "#ifdef HLSL\n"
2651 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2652 "#else\n"
2653 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2654 "#endif\n"
2655 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2656 "#endif\n"
2657 "\n"
2658 "       // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2664 "#endif\n"
2665 "\n"
2666 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2670 "}\n"
2671 "#endif // VERTEX_SHADER\n"
2672 "\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2674 "void main\n"
2675 "(\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2684 "#endif\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2689 "#endif\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2692 "#endif\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2695 ")\n"
2696 "{\n"
2697 "       float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 "       // apply offsetmapping\n"
2700 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEALPHAKILL\n"
2705 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2706 "               discard;\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2719 "#else\n"
2720 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2722 "#endif\n"
2723 "\n"
2724 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2725 "}\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2728 "\n"
2729 "\n"
2730 "\n"
2731 "\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2734 "void main\n"
2735 "(\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2741 ")\n"
2742 "{\n"
2743 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2745 "}\n"
2746 "#endif // VERTEX_SHADER\n"
2747 "\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2749 "void main\n"
2750 "(\n"
2751 "#ifdef HLSL\n"
2752 "float2 Pixel : VPOS,\n"
2753 "#else\n"
2754 "float2 Pixel : WPOS,\n"
2755 "#endif\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2766 "#endif\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2770 "\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2778 "# else\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2786 "# else\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2788 "# endif\n"
2789 "#endif\n"
2790 "\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2798 "# else\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2800 "# endif\n"
2801 "#endif\n"
2802 "\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2806 "#endif\n"
2807 "\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2810 ")\n"
2811 "{\n"
2812 "       // calculate viewspace pixel position\n"
2813 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 "       float3 position;\n"
2816 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 "       // decode viewspace pixel normal\n"
2819 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 "       // surfacenormal = pixel normal in viewspace\n"
2822 "       // LightVector = pixel to light in viewspace\n"
2823 "       // CubeVector = position in lightspace\n"
2824 "       // eyevector = pixel to view in viewspace\n"
2825 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 "       // calculate diffuse shading\n"
2829 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2831 "#endif\n"
2832 "#ifdef USESPECULAR\n"
2833 "       // calculate directional shading\n"
2834 "       float3 eyevector = position * -1.0;\n"
2835 "#  ifdef USEEXACTSPECULARMATH\n"
2836 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2837 "#  else\n"
2838 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2840 "#  endif\n"
2841 "#endif\n"
2842 "\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 "       fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2847 "# endif\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2850 "# endif\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2853 "# endif\n"
2854 "\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2857 "#endif\n"
2858 "       );\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USEDIFFUSE\n"
2862 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2863 "#else\n"
2864 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2865 "#endif\n"
2866 "#ifdef USESPECULAR\n"
2867 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2868 "#else\n"
2869 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2870 "#endif\n"
2871 "\n"
2872 "# ifdef USECUBEFILTER\n"
2873 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 "       gl_FragData0.rgb *= cubecolor;\n"
2875 "       gl_FragData1.rgb *= cubecolor;\n"
2876 "# endif\n"
2877 "}\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2880 "\n"
2881 "\n"
2882 "\n"
2883 "\n"
2884 "#ifdef VERTEX_SHADER\n"
2885 "void main\n"
2886 "(\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2891 "#endif\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2897 "\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2902 "#endif\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2911 "#endif\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2915 "#endif\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2918 "#endif\n"
2919 "\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2924 "#endif\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2927 "#endif\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "#endif\n"
2931 "#ifdef USEFOG\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2933 "#endif\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2936 "#endif\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "out float4 gl_Position : POSITION\n"
2949 ")\n"
2950 "{\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2952 "#ifdef HLSL\n"
2953 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2954 "#else\n"
2955 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2956 "#endif\n"
2957 "#endif\n"
2958 "       // copy the surface texcoord\n"
2959 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2962 "#endif\n"
2963 "#ifdef USELIGHTMAP\n"
2964 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2965 "#endif\n"
2966 "\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 "       // transform vertex position into light attenuation/cubemap space\n"
2969 "       // (-1 to +1 across the light box)\n"
2970 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2971 "\n"
2972 "# ifdef USEDIFFUSE\n"
2973 "       // transform unnormalized light direction into tangent space\n"
2974 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 "       //  normalize it per pixel)\n"
2976 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2980 "# endif\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2987 "#endif\n"
2988 "\n"
2989 "       // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEFOG\n"
2998 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3004 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3005 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3006 "#endif\n"
3007 "\n"
3008 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3010 "\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USEREFLECTION\n"
3016 "       ModelViewProjectionPosition = gl_Position;\n"
3017 "#endif\n"
3018 "}\n"
3019 "#endif // VERTEX_SHADER\n"
3020 "\n"
3021 "\n"
3022 "\n"
3023 "\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3025 "void main\n"
3026 "(\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "#ifdef HLSL\n"
3029 "float2 Pixel : VPOS,\n"
3030 "#else\n"
3031 "float2 Pixel : WPOS,\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3038 "#endif\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3041 "#endif\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3044 "#endif\n"
3045 "#ifdef USEFOG\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3047 "#endif\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3050 "#endif\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3053 "#endif\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3056 "#endif\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3061 "#endif\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3064 "#endif\n"
3065 "\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3070 "#endif\n"
3071 "#ifdef USEGLOW\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3073 "#endif\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3079 "#endif\n"
3080 "#ifdef USEGLOW\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3082 "#endif\n"
3083 "#endif\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3087 "#endif\n"
3088 "#ifdef USEFOG\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3091 "#endif\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3094 "#endif\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3097 "#endif\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3105 "#endif\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3114 "#endif\n"
3115 "#ifdef USEFOG\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3120 "#endif\n"
3121 "\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3130 "#endif\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3135 "#ifdef USEGLOW\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3137 "#endif\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3144 "#endif\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3149 "#endif\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3152 "#endif\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3155 "#endif\n"
3156 "\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3160 "#endif\n"
3161 "\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3163 "\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3167 "# else\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3169 "# endif\n"
3170 "#endif\n"
3171 "\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3175 "# else\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3177 "# endif\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3182 "#endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3187 "# else\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3189 "# endif\n"
3190 "#endif\n"
3191 "\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3195 "#endif\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3197 "\n"
3198 "out float4 gl_FragColor : COLOR\n"
3199 ")\n"
3200 "{\n"
3201 "       float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3204 "#endif\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 "       // apply offsetmapping\n"
3207 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3209 "#endif\n"
3210 "\n"
3211 "       // combine the diffuse textures (base, pants, shirt)\n"
3212 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 "       if (color.a < 0.5)\n"
3215 "               discard;\n"
3216 "#endif\n"
3217 "       color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3220 "#endif\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3226 "       color.a = 1.0;\n"
3227 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3228 "#endif\n"
3229 "\n"
3230 "       // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3233 "#else\n"
3234 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3235 "#endif\n"
3236 "\n"
3237 "       // get the material colors\n"
3238 "       half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3242 "# else\n"
3243 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3244 "# endif\n"
3245 "#endif\n"
3246 "\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3252 "#endif\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 "       // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 "       half3 lightnormal = half3(normalize(LightVector));\n"
3261 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3266 "#else\n"
3267 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3269 "#endif\n"
3270 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3271 "#endif\n"
3272 "#else\n"
3273 "       color.rgb = diffusetex * Color_Ambient;\n"
3274 "#endif\n"
3275 "       color.rgb *= LightColor;\n"
3276 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3281 "# endif\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3284 "# endif\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3287 "# endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3291 "#endif\n"
3292 "       ));\n"
3293 "\n"
3294 "#endif\n"
3295 "# ifdef USECUBEFILTER\n"
3296 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3297 "# endif\n"
3298 "\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3305 "#else\n"
3306 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "//     color.r = half(shadowmaptc.z);\n"
3314 "#endif\n"
3315 "//     color.r = 1;\n"
3316 "#endif\n"
3317 "//     color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3319 "\n"
3320 "\n"
3321 "\n"
3322 "\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3324 "#define SHADING\n"
3325 "#ifdef USEDIFFUSE\n"
3326 "       half3 lightnormal = half3(normalize(LightVector));\n"
3327 "#endif\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3331 "#define SHADING\n"
3332 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 "       // convert modelspace light vector to tangentspace\n"
3336 "       half3 lightnormal;\n"
3337 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3352 "#define SHADING\n"
3353 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3356 "#endif\n"
3357 "\n"
3358 "\n"
3359 "\n"
3360 "\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 "       color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3370 "\n"
3371 "\n"
3372 "\n"
3373 "\n"
3374 "#ifdef SHADING\n"
3375 "# ifdef USEDIFFUSE\n"
3376 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "#  ifdef USESPECULAR\n"
3378 "#   ifdef USEEXACTSPECULARMATH\n"
3379 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3380 "#   else\n"
3381 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3383 "#   endif\n"
3384 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3385 "#  else\n"
3386 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3387 "#  endif\n"
3388 "# else\n"
3389 "       color.rgb = diffusetex * Color_Ambient;\n"
3390 "# endif\n"
3391 "#endif\n"
3392 "\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3397 "# endif\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3400 "# endif\n"
3401 "       );\n"
3402 "#endif\n"
3403 "\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef USEGLOW\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3413 "#else\n"
3414 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3415 "#endif\n"
3416 "#endif\n"
3417 "\n"
3418 "#ifdef USEFOG\n"
3419 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3420 "#endif\n"
3421 "\n"
3422 "       // 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"
3423 "#ifdef USEREFLECTION\n"
3424 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 "       // FIXME temporary hack to detect the case that the reflection\n"
3429 "       // gets blackened at edges due to leaving the area that contains actual\n"
3430 "       // content.\n"
3431 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3432 "       // 'appening.\n"
3433 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3439 "#endif\n"
3440 "\n"
3441 "       gl_FragColor = float4(color);\n"
3442 "}\n"
3443 "#endif // FRAGMENT_SHADER\n"
3444 "\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3454 ;
3455
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3459
3460 //=======================================================================================================================================================
3461
3462 typedef struct shaderpermutationinfo_s
3463 {
3464         const char *pretext;
3465         const char *name;
3466 }
3467 shaderpermutationinfo_t;
3468
3469 typedef struct shadermodeinfo_s
3470 {
3471         const char *vertexfilename;
3472         const char *geometryfilename;
3473         const char *fragmentfilename;
3474         const char *pretext;
3475         const char *name;
3476 }
3477 shadermodeinfo_t;
3478
3479 typedef enum shaderpermutation_e
3480 {
3481         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3512 }
3513 shaderpermutation_t;
3514
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3517 {
3518         {"#define USEDIFFUSE\n", " diffuse"},
3519         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520         {"#define USEVIEWTINT\n", " viewtint"},
3521         {"#define USECOLORMAPPING\n", " colormapping"},
3522         {"#define USESATURATION\n", " saturation"},
3523         {"#define USEFOGINSIDE\n", " foginside"},
3524         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526         {"#define USEGAMMARAMPS\n", " gammaramps"},
3527         {"#define USECUBEFILTER\n", " cubefilter"},
3528         {"#define USEGLOW\n", " glow"},
3529         {"#define USEBLOOM\n", " bloom"},
3530         {"#define USESPECULAR\n", " specular"},
3531         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533         {"#define USEREFLECTION\n", " reflection"},
3534         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545         {"#define USEALPHAKILL\n", " alphakill"},
3546         {"#define USEREFLECTCUBE\n", " reflectcube"},
3547 };
3548
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3551 {
3552         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3567         SHADERMODE_COUNT
3568 }
3569 shadermode_t;
3570
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3573 {
3574         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3589 };
3590
3591 #ifdef SUPPORTCG
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3593 {
3594         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3609 };
3610 #endif
3611
3612 #ifdef SUPPORTD3D
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3614 {
3615         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3630 };
3631 #endif
3632
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_glsl_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         int program;
3645         /// locations of detected uniforms in program object, or -1 if not found
3646         int loc_Texture_First;
3647         int loc_Texture_Second;
3648         int loc_Texture_GammaRamps;
3649         int loc_Texture_Normal;
3650         int loc_Texture_Color;
3651         int loc_Texture_Gloss;
3652         int loc_Texture_Glow;
3653         int loc_Texture_SecondaryNormal;
3654         int loc_Texture_SecondaryColor;
3655         int loc_Texture_SecondaryGloss;
3656         int loc_Texture_SecondaryGlow;
3657         int loc_Texture_Pants;
3658         int loc_Texture_Shirt;
3659         int loc_Texture_FogHeightTexture;
3660         int loc_Texture_FogMask;
3661         int loc_Texture_Lightmap;
3662         int loc_Texture_Deluxemap;
3663         int loc_Texture_Attenuation;
3664         int loc_Texture_Cube;
3665         int loc_Texture_Refraction;
3666         int loc_Texture_Reflection;
3667         int loc_Texture_ShadowMapRect;
3668         int loc_Texture_ShadowMapCube;
3669         int loc_Texture_ShadowMap2D;
3670         int loc_Texture_CubeProjection;
3671         int loc_Texture_ScreenDepth;
3672         int loc_Texture_ScreenNormalMap;
3673         int loc_Texture_ScreenDiffuse;
3674         int loc_Texture_ScreenSpecular;
3675         int loc_Texture_ReflectMask;
3676         int loc_Texture_ReflectCube;
3677         int loc_Alpha;
3678         int loc_BloomBlur_Parameters;
3679         int loc_ClientTime;
3680         int loc_Color_Ambient;
3681         int loc_Color_Diffuse;
3682         int loc_Color_Specular;
3683         int loc_Color_Glow;
3684         int loc_Color_Pants;
3685         int loc_Color_Shirt;
3686         int loc_DeferredColor_Ambient;
3687         int loc_DeferredColor_Diffuse;
3688         int loc_DeferredColor_Specular;
3689         int loc_DeferredMod_Diffuse;
3690         int loc_DeferredMod_Specular;
3691         int loc_DistortScaleRefractReflect;
3692         int loc_EyePosition;
3693         int loc_FogColor;
3694         int loc_FogHeightFade;
3695         int loc_FogPlane;
3696         int loc_FogPlaneViewDist;
3697         int loc_FogRangeRecip;
3698         int loc_LightColor;
3699         int loc_LightDir;
3700         int loc_LightPosition;
3701         int loc_OffsetMapping_Scale;
3702         int loc_PixelSize;
3703         int loc_ReflectColor;
3704         int loc_ReflectFactor;
3705         int loc_ReflectOffset;
3706         int loc_RefractColor;
3707         int loc_Saturation;
3708         int loc_ScreenCenterRefractReflect;
3709         int loc_ScreenScaleRefractReflect;
3710         int loc_ScreenToDepth;
3711         int loc_ShadowMap_Parameters;
3712         int loc_ShadowMap_TextureScale;
3713         int loc_SpecularPower;
3714         int loc_UserVec1;
3715         int loc_UserVec2;
3716         int loc_UserVec3;
3717         int loc_UserVec4;
3718         int loc_ViewTintColor;
3719         int loc_ViewToLight;
3720         int loc_ModelToLight;
3721         int loc_TexMatrix;
3722         int loc_BackgroundTexMatrix;
3723         int loc_ModelViewProjectionMatrix;
3724         int loc_ModelViewMatrix;
3725         int loc_PixelToScreenTexCoord;
3726         int loc_ModelToReflectCube;
3727         int loc_ShadowMapMatrix;
3728         int loc_BloomColorSubtract;
3729 }
3730 r_glsl_permutation_t;
3731
3732 #define SHADERPERMUTATION_HASHSIZE 256
3733
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3740
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3742 {
3743         //unsigned int hashdepth = 0;
3744         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745         r_glsl_permutation_t *p;
3746         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3747         {
3748                 if (p->mode == mode && p->permutation == permutation)
3749                 {
3750                         //if (hashdepth > 10)
3751                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3752                         return p;
3753                 }
3754                 //hashdepth++;
3755         }
3756         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3757         p->mode = mode;
3758         p->permutation = permutation;
3759         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760         r_glsl_permutationhash[mode][hashindex] = p;
3761         //if (hashdepth > 10)
3762         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3763         return p;
3764 }
3765
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3767 {
3768         char *shaderstring;
3769         if (!filename || !filename[0])
3770                 return NULL;
3771         if (!strcmp(filename, "glsl/default.glsl"))
3772         {
3773                 if (!glslshaderstring)
3774                 {
3775                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776                         if (glslshaderstring)
3777                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3778                         else
3779                                 glslshaderstring = (char *)builtinshaderstring;
3780                 }
3781                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783                 return shaderstring;
3784         }
3785         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3786         if (shaderstring)
3787         {
3788                 if (printfromdisknotice)
3789                         Con_DPrintf("from disk %s... ", filename);
3790                 return shaderstring;
3791         }
3792         return shaderstring;
3793 }
3794
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3796 {
3797         int i;
3798         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799         int vertstrings_count = 0;
3800         int geomstrings_count = 0;
3801         int fragstrings_count = 0;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         const char *vertstrings_list[32+3];
3804         const char *geomstrings_list[32+3];
3805         const char *fragstrings_list[32+3];
3806         char permutationname[256];
3807
3808         if (p->compiled)
3809                 return;
3810         p->compiled = true;
3811         p->program = 0;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         // compile the shader program
3865         if (vertstrings_count + geomstrings_count + fragstrings_count)
3866                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3867         if (p->program)
3868         {
3869                 CHECKGLERROR
3870                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871                 // look up all the uniform variable names we care about, so we don't
3872                 // have to look them up every time we set them
3873
3874                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3875                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3876                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3879                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3906                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3908                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3911                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3912                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3913                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3921                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3922                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3924                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3927                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3928                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3929                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3931                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3932                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3935                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3936                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3942                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3943                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3944                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3945                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3946                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3948                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3949                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3950                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957                 // initialize the samplers to refer to the texture units we use
3958                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3959                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3960                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3961                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3962                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3963                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3964                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3965                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3969                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3970                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3971                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3973                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3974                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3975                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3976                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3977                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3978                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3979                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3988                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3989                 CHECKGLERROR
3990                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3991         }
3992         else
3993                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3994
3995         // free the strings
3996         if (vertexstring)
3997                 Mem_Free(vertexstring);
3998         if (geometrystring)
3999                 Mem_Free(geometrystring);
4000         if (fragmentstring)
4001                 Mem_Free(fragmentstring);
4002 }
4003
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4005 {
4006         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007         if (r_glsl_permutation != perm)
4008         {
4009                 r_glsl_permutation = perm;
4010                 if (!r_glsl_permutation->program)
4011                 {
4012                         if (!r_glsl_permutation->compiled)
4013                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4014                         if (!r_glsl_permutation->program)
4015                         {
4016                                 // remove features until we find a valid permutation
4017                                 int i;
4018                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4019                                 {
4020                                         // reduce i more quickly whenever it would not remove any bits
4021                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022                                         if (!(permutation & j))
4023                                                 continue;
4024                                         permutation -= j;
4025                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026                                         if (!r_glsl_permutation->compiled)
4027                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4028                                         if (r_glsl_permutation->program)
4029                                                 break;
4030                                 }
4031                                 if (i >= SHADERPERMUTATION_COUNT)
4032                                 {
4033                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035                                         qglUseProgramObjectARB(0);CHECKGLERROR
4036                                         return; // no bit left to clear, entire mode is broken
4037                                 }
4038                         }
4039                 }
4040                 CHECKGLERROR
4041                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4042         }
4043         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4046 }
4047
4048 #ifdef SUPPORTCG
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4052 {
4053         /// hash lookup data
4054         struct r_cg_permutation_s *hashnext;
4055         unsigned int mode;
4056         unsigned int permutation;
4057
4058         /// indicates if we have tried compiling this permutation already
4059         qboolean compiled;
4060         /// 0 if compilation failed
4061         CGprogram vprogram;
4062         CGprogram fprogram;
4063         /// locations of detected parameters in programs, or NULL if not found
4064         CGparameter vp_EyePosition;
4065         CGparameter vp_FogPlane;
4066         CGparameter vp_LightDir;
4067         CGparameter vp_LightPosition;
4068         CGparameter vp_ModelToLight;
4069         CGparameter vp_TexMatrix;
4070         CGparameter vp_BackgroundTexMatrix;
4071         CGparameter vp_ModelViewProjectionMatrix;
4072         CGparameter vp_ModelViewMatrix;
4073         CGparameter vp_ShadowMapMatrix;
4074
4075         CGparameter fp_Texture_First;
4076         CGparameter fp_Texture_Second;
4077         CGparameter fp_Texture_GammaRamps;
4078         CGparameter fp_Texture_Normal;
4079         CGparameter fp_Texture_Color;
4080         CGparameter fp_Texture_Gloss;
4081         CGparameter fp_Texture_Glow;
4082         CGparameter fp_Texture_SecondaryNormal;
4083         CGparameter fp_Texture_SecondaryColor;
4084         CGparameter fp_Texture_SecondaryGloss;
4085         CGparameter fp_Texture_SecondaryGlow;
4086         CGparameter fp_Texture_Pants;
4087         CGparameter fp_Texture_Shirt;
4088         CGparameter fp_Texture_FogHeightTexture;
4089         CGparameter fp_Texture_FogMask;
4090         CGparameter fp_Texture_Lightmap;
4091         CGparameter fp_Texture_Deluxemap;
4092         CGparameter fp_Texture_Attenuation;
4093         CGparameter fp_Texture_Cube;
4094         CGparameter fp_Texture_Refraction;
4095         CGparameter fp_Texture_Reflection;
4096         CGparameter fp_Texture_ShadowMapRect;
4097         CGparameter fp_Texture_ShadowMapCube;
4098         CGparameter fp_Texture_ShadowMap2D;
4099         CGparameter fp_Texture_CubeProjection;
4100         CGparameter fp_Texture_ScreenDepth;
4101         CGparameter fp_Texture_ScreenNormalMap;
4102         CGparameter fp_Texture_ScreenDiffuse;
4103         CGparameter fp_Texture_ScreenSpecular;
4104         CGparameter fp_Texture_ReflectMask;
4105         CGparameter fp_Texture_ReflectCube;
4106         CGparameter fp_Alpha;
4107         CGparameter fp_BloomBlur_Parameters;
4108         CGparameter fp_ClientTime;
4109         CGparameter fp_Color_Ambient;
4110         CGparameter fp_Color_Diffuse;
4111         CGparameter fp_Color_Specular;
4112         CGparameter fp_Color_Glow;
4113         CGparameter fp_Color_Pants;
4114         CGparameter fp_Color_Shirt;
4115         CGparameter fp_DeferredColor_Ambient;
4116         CGparameter fp_DeferredColor_Diffuse;
4117         CGparameter fp_DeferredColor_Specular;
4118         CGparameter fp_DeferredMod_Diffuse;
4119         CGparameter fp_DeferredMod_Specular;
4120         CGparameter fp_DistortScaleRefractReflect;
4121         CGparameter fp_EyePosition;
4122         CGparameter fp_FogColor;
4123         CGparameter fp_FogHeightFade;
4124         CGparameter fp_FogPlane;
4125         CGparameter fp_FogPlaneViewDist;
4126         CGparameter fp_FogRangeRecip;
4127         CGparameter fp_LightColor;
4128         CGparameter fp_LightDir;
4129         CGparameter fp_LightPosition;
4130         CGparameter fp_OffsetMapping_Scale;
4131         CGparameter fp_PixelSize;
4132         CGparameter fp_ReflectColor;
4133         CGparameter fp_ReflectFactor;
4134         CGparameter fp_ReflectOffset;
4135         CGparameter fp_RefractColor;
4136         CGparameter fp_Saturation;
4137         CGparameter fp_ScreenCenterRefractReflect;
4138         CGparameter fp_ScreenScaleRefractReflect;
4139         CGparameter fp_ScreenToDepth;
4140         CGparameter fp_ShadowMap_Parameters;
4141         CGparameter fp_ShadowMap_TextureScale;
4142         CGparameter fp_SpecularPower;
4143         CGparameter fp_UserVec1;
4144         CGparameter fp_UserVec2;
4145         CGparameter fp_UserVec3;
4146         CGparameter fp_UserVec4;
4147         CGparameter fp_ViewTintColor;
4148         CGparameter fp_ViewToLight;
4149         CGparameter fp_PixelToScreenTexCoord;
4150         CGparameter fp_ModelToReflectCube;
4151         CGparameter fp_BloomColorSubtract;
4152 }
4153 r_cg_permutation_t;
4154
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4161
4162 #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));}}
4163
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4165 {
4166         //unsigned int hashdepth = 0;
4167         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168         r_cg_permutation_t *p;
4169         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4170         {
4171                 if (p->mode == mode && p->permutation == permutation)
4172                 {
4173                         //if (hashdepth > 10)
4174                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4175                         return p;
4176                 }
4177                 //hashdepth++;
4178         }
4179         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4180         p->mode = mode;
4181         p->permutation = permutation;
4182         p->hashnext = r_cg_permutationhash[mode][hashindex];
4183         r_cg_permutationhash[mode][hashindex] = p;
4184         //if (hashdepth > 10)
4185         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4186         return p;
4187 }
4188
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4190 {
4191         char *shaderstring;
4192         if (!filename || !filename[0])
4193                 return NULL;
4194         if (!strcmp(filename, "cg/default.cg"))
4195         {
4196                 if (!cgshaderstring)
4197                 {
4198                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4199                         if (cgshaderstring)
4200                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4201                         else
4202                                 cgshaderstring = (char *)builtincgshaderstring;
4203                 }
4204                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206                 return shaderstring;
4207         }
4208         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4209         if (shaderstring)
4210         {
4211                 if (printfromdisknotice)
4212                         Con_DPrintf("from disk %s... ", filename);
4213                 return shaderstring;
4214         }
4215         return shaderstring;
4216 }
4217
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4219 {
4220         // TODO: load or create .fp and .vp shader files
4221 }
4222
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4224 {
4225         int i;
4226         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227         int vertstrings_count = 0, vertstring_length = 0;
4228         int geomstrings_count = 0, geomstring_length = 0;
4229         int fragstrings_count = 0, fragstring_length = 0;
4230         char *t;
4231         char *vertexstring, *geometrystring, *fragmentstring;
4232         char *vertstring, *geomstring, *fragstring;
4233         const char *vertstrings_list[32+3];
4234         const char *geomstrings_list[32+3];
4235         const char *fragstrings_list[32+3];
4236         char permutationname[256];
4237         char cachename[256];
4238         CGprofile vertexProfile;
4239         CGprofile fragmentProfile;
4240
4241         if (p->compiled)
4242                 return;
4243         p->compiled = true;
4244         p->vprogram = NULL;
4245         p->fprogram = NULL;
4246
4247         permutationname[0] = 0;
4248         cachename[0] = 0;
4249         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4250         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4252
4253         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254         strlcat(cachename, "cg/", sizeof(cachename));
4255
4256         // the first pretext is which type of shader to compile as
4257         // (later these will all be bound together as a program object)
4258         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4261
4262         // the second pretext is the mode (for example a light source)
4263         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267         strlcat(cachename, modeinfo->name, sizeof(cachename));
4268
4269         // now add all the permutation pretexts
4270         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271         {
4272                 if (permutation & (1<<i))
4273                 {
4274                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4279                 }
4280                 else
4281                 {
4282                         // keep line numbers correct
4283                         vertstrings_list[vertstrings_count++] = "\n";
4284                         geomstrings_list[geomstrings_count++] = "\n";
4285                         fragstrings_list[fragstrings_count++] = "\n";
4286                 }
4287         }
4288
4289         // replace spaces in the cachename with _ characters
4290         for (i = 0;cachename[i];i++)
4291                 if (cachename[i] == ' ')
4292                         cachename[i] = '_';
4293
4294         // now append the shader text itself
4295         vertstrings_list[vertstrings_count++] = vertexstring;
4296         geomstrings_list[geomstrings_count++] = geometrystring;
4297         fragstrings_list[fragstrings_count++] = fragmentstring;
4298
4299         // if any sources were NULL, clear the respective list
4300         if (!vertexstring)
4301                 vertstrings_count = 0;
4302         if (!geometrystring)
4303                 geomstrings_count = 0;
4304         if (!fragmentstring)
4305                 fragstrings_count = 0;
4306
4307         vertstring_length = 0;
4308         for (i = 0;i < vertstrings_count;i++)
4309                 vertstring_length += strlen(vertstrings_list[i]);
4310         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4313
4314         geomstring_length = 0;
4315         for (i = 0;i < geomstrings_count;i++)
4316                 geomstring_length += strlen(geomstrings_list[i]);
4317         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4320
4321         fragstring_length = 0;
4322         for (i = 0;i < fragstrings_count;i++)
4323                 fragstring_length += strlen(fragstrings_list[i]);
4324         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4327
4328         CHECKGLERROR
4329         CHECKCGERROR
4330         //vertexProfile = CG_PROFILE_ARBVP1;
4331         //fragmentProfile = CG_PROFILE_ARBFP1;
4332         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4337         CHECKGLERROR
4338
4339         // try to load the cached shader, or generate one
4340         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4341
4342         // if caching failed, do a dynamic compile for now
4343         CHECKCGERROR
4344         if (vertstring[0] && !p->vprogram)
4345                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4346         CHECKCGERROR
4347         if (fragstring[0] && !p->fprogram)
4348                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4349         CHECKCGERROR
4350
4351         // look up all the uniform variable names we care about, so we don't
4352         // have to look them up every time we set them
4353         if (p->vprogram)
4354         {
4355                 CHECKCGERROR
4356                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4359                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4360                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4361                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4362                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4368                 CHECKCGERROR
4369         }
4370         if (p->fprogram)
4371         {
4372                 CHECKCGERROR
4373                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4376                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4407                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4409                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4422                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4423                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4425                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4428                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4429                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4430                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4432                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4436                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4437                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4444                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4445                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4446                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4447                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4452                 CHECKCGERROR
4453         }
4454
4455         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4457         else
4458                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4459
4460         // free the strings
4461         if (vertstring)
4462                 Mem_Free(vertstring);
4463         if (geomstring)
4464                 Mem_Free(geomstring);
4465         if (fragstring)
4466                 Mem_Free(fragstring);
4467         if (vertexstring)
4468                 Mem_Free(vertexstring);
4469         if (geometrystring)
4470                 Mem_Free(geometrystring);
4471         if (fragmentstring)
4472                 Mem_Free(fragmentstring);
4473 }
4474
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4476 {
4477         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4478         CHECKGLERROR
4479         CHECKCGERROR
4480         if (r_cg_permutation != perm)
4481         {
4482                 r_cg_permutation = perm;
4483                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4484                 {
4485                         if (!r_cg_permutation->compiled)
4486                                 R_CG_CompilePermutation(perm, mode, permutation);
4487                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4488                         {
4489                                 // remove features until we find a valid permutation
4490                                 int i;
4491                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4492                                 {
4493                                         // reduce i more quickly whenever it would not remove any bits
4494                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495                                         if (!(permutation & j))
4496                                                 continue;
4497                                         permutation -= j;
4498                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499                                         if (!r_cg_permutation->compiled)
4500                                                 R_CG_CompilePermutation(perm, mode, permutation);
4501                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4502                                                 break;
4503                                 }
4504                                 if (i >= SHADERPERMUTATION_COUNT)
4505                                 {
4506                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508                                         return; // no bit left to clear, entire mode is broken
4509                                 }
4510                         }
4511                 }
4512                 CHECKGLERROR
4513                 CHECKCGERROR
4514                 if (r_cg_permutation->vprogram)
4515                 {
4516                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4519                 }
4520                 else
4521                 {
4522                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4524                 }
4525                 if (r_cg_permutation->fprogram)
4526                 {
4527                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4530                 }
4531                 else
4532                 {
4533                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4535                 }
4536         }
4537         CHECKCGERROR
4538         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4541 }
4542
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4544 {
4545         cgGLSetTextureParameter(param, R_GetTexture(tex));
4546         cgGLEnableTextureParameter(param);
4547 }
4548 #endif
4549
4550 #ifdef SUPPORTD3D
4551
4552 #ifdef SUPPORTD3D
4553 #include <d3d9.h>
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4556 #endif
4557
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4560 {
4561         /// hash lookup data
4562         struct r_hlsl_permutation_s *hashnext;
4563         unsigned int mode;
4564         unsigned int permutation;
4565
4566         /// indicates if we have tried compiling this permutation already
4567         qboolean compiled;
4568         /// NULL if compilation failed
4569         IDirect3DVertexShader9 *vertexshader;
4570         IDirect3DPixelShader9 *pixelshader;
4571 }
4572 r_hlsl_permutation_t;
4573
4574 typedef enum D3DVSREGISTER_e
4575 {
4576         D3DVSREGISTER_TexMatrix = 0, // float4x4
4577         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581         D3DVSREGISTER_ModelToLight = 20, // float4x4
4582         D3DVSREGISTER_EyePosition = 24,
4583         D3DVSREGISTER_FogPlane = 25,
4584         D3DVSREGISTER_LightDir = 26,
4585         D3DVSREGISTER_LightPosition = 27,
4586 }
4587 D3DVSREGISTER_t;
4588
4589 typedef enum D3DPSREGISTER_e
4590 {
4591         D3DPSREGISTER_Alpha = 0,
4592         D3DPSREGISTER_BloomBlur_Parameters = 1,
4593         D3DPSREGISTER_ClientTime = 2,
4594         D3DPSREGISTER_Color_Ambient = 3,
4595         D3DPSREGISTER_Color_Diffuse = 4,
4596         D3DPSREGISTER_Color_Specular = 5,
4597         D3DPSREGISTER_Color_Glow = 6,
4598         D3DPSREGISTER_Color_Pants = 7,
4599         D3DPSREGISTER_Color_Shirt = 8,
4600         D3DPSREGISTER_DeferredColor_Ambient = 9,
4601         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602         D3DPSREGISTER_DeferredColor_Specular = 11,
4603         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604         D3DPSREGISTER_DeferredMod_Specular = 13,
4605         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606         D3DPSREGISTER_EyePosition = 15, // unused
4607         D3DPSREGISTER_FogColor = 16,
4608         D3DPSREGISTER_FogHeightFade = 17,
4609         D3DPSREGISTER_FogPlane = 18,
4610         D3DPSREGISTER_FogPlaneViewDist = 19,
4611         D3DPSREGISTER_FogRangeRecip = 20,
4612         D3DPSREGISTER_LightColor = 21,
4613         D3DPSREGISTER_LightDir = 22, // unused
4614         D3DPSREGISTER_LightPosition = 23,
4615         D3DPSREGISTER_OffsetMapping_Scale = 24,
4616         D3DPSREGISTER_PixelSize = 25,
4617         D3DPSREGISTER_ReflectColor = 26,
4618         D3DPSREGISTER_ReflectFactor = 27,
4619         D3DPSREGISTER_ReflectOffset = 28,
4620         D3DPSREGISTER_RefractColor = 29,
4621         D3DPSREGISTER_Saturation = 30,
4622         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624         D3DPSREGISTER_ScreenToDepth = 33,
4625         D3DPSREGISTER_ShadowMap_Parameters = 34,
4626         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627         D3DPSREGISTER_SpecularPower = 36,
4628         D3DPSREGISTER_UserVec1 = 37,
4629         D3DPSREGISTER_UserVec2 = 38,
4630         D3DPSREGISTER_UserVec3 = 39,
4631         D3DPSREGISTER_UserVec4 = 40,
4632         D3DPSREGISTER_ViewTintColor = 41,
4633         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634         D3DPSREGISTER_BloomColorSubtract = 43,
4635         D3DPSREGISTER_ViewToLight = 44, // float4x4
4636         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4637         // next at 52
4638 }
4639 D3DPSREGISTER_t;
4640
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4647
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4649 {
4650         //unsigned int hashdepth = 0;
4651         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652         r_hlsl_permutation_t *p;
4653         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4654         {
4655                 if (p->mode == mode && p->permutation == permutation)
4656                 {
4657                         //if (hashdepth > 10)
4658                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4659                         return p;
4660                 }
4661                 //hashdepth++;
4662         }
4663         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4664         p->mode = mode;
4665         p->permutation = permutation;
4666         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667         r_hlsl_permutationhash[mode][hashindex] = p;
4668         //if (hashdepth > 10)
4669         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4670         return p;
4671 }
4672
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4674 {
4675         char *shaderstring;
4676         if (!filename || !filename[0])
4677                 return NULL;
4678         if (!strcmp(filename, "hlsl/default.hlsl"))
4679         {
4680                 if (!hlslshaderstring)
4681                 {
4682                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683                         if (hlslshaderstring)
4684                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4685                         else
4686                                 hlslshaderstring = (char *)builtincgshaderstring;
4687                 }
4688                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690                 return shaderstring;
4691         }
4692         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4693         if (shaderstring)
4694         {
4695                 if (printfromdisknotice)
4696                         Con_DPrintf("from disk %s... ", filename);
4697                 return shaderstring;
4698         }
4699         return shaderstring;
4700 }
4701
4702 #include <d3dx9.h>
4703 #include <d3dx9mesh.h>
4704 #ifdef _MSC_VER
4705 #pragma comment(lib, "d3dx9.lib")
4706 #endif
4707
4708 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4709 {
4710         DWORD *vsbin = NULL;
4711         DWORD *psbin = NULL;
4712         fs_offset_t vsbinsize;
4713         fs_offset_t psbinsize;
4714 //      IDirect3DVertexShader9 *vs = NULL;
4715 //      IDirect3DPixelShader9 *ps = NULL;
4716         ID3DXBuffer *vslog = NULL;
4717         ID3DXBuffer *vsbuffer = NULL;
4718         ID3DXConstantTable *vsconstanttable = NULL;
4719         ID3DXBuffer *pslog = NULL;
4720         ID3DXBuffer *psbuffer = NULL;
4721         ID3DXConstantTable *psconstanttable = NULL;
4722         int vsresult = 0;
4723         int psresult = 0;
4724         char temp[MAX_INPUTLINE];
4725         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4726         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4727         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4728         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4729         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4730         if ((!vsbin && vertstring) || (!psbin && fragstring))
4731         {
4732                 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4733                 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4734                 if (vertstring && vertstring[0])
4735                 {
4736                         vsresult = D3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
4737                         if (vsbuffer)
4738                         {
4739                                 vsbinsize = vsbuffer->GetBufferSize();
4740                                 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4741                                 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4742                                 vsbuffer->Release();
4743                         }
4744                         if (vslog)
4745                         {
4746                                 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4747                                 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4748                                 vslog->Release();
4749                         }
4750                 }
4751                 if (fragstring && fragstring[0])
4752                 {
4753                         psresult = D3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
4754                         if (psbuffer)
4755                         {
4756                                 psbinsize = psbuffer->GetBufferSize();
4757                                 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4758                                 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4759                                 psbuffer->Release();
4760                         }
4761                         if (pslog)
4762                         {
4763                                 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4764                                 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4765                                 pslog->Release();
4766                         }
4767                 }
4768         }
4769         if (vsbin)
4770         {
4771                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4772                 if (FAILED(vsresult))
4773                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4774         }
4775         if (psbin)
4776         {
4777                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4778                 if (FAILED(psresult))
4779                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4780         }
4781         // free the shader data
4782         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4783         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4784 }
4785
4786 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4787 {
4788         int i;
4789         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4790         int vertstrings_count = 0, vertstring_length = 0;
4791         int geomstrings_count = 0, geomstring_length = 0;
4792         int fragstrings_count = 0, fragstring_length = 0;
4793         char *t;
4794         char *vertexstring, *geometrystring, *fragmentstring;
4795         char *vertstring, *geomstring, *fragstring;
4796         const char *vertstrings_list[32+3];
4797         const char *geomstrings_list[32+3];
4798         const char *fragstrings_list[32+3];
4799         char permutationname[256];
4800         char cachename[256];
4801
4802         if (p->compiled)
4803                 return;
4804         p->compiled = true;
4805         p->vertexshader = NULL;
4806         p->pixelshader = NULL;
4807
4808         permutationname[0] = 0;
4809         cachename[0] = 0;
4810         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4811         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4812         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4813
4814         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4815         strlcat(cachename, "hlsl/", sizeof(cachename));
4816
4817         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4818         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4819         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4820         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4821
4822         // the first pretext is which type of shader to compile as
4823         // (later these will all be bound together as a program object)
4824         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4825         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4826         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4827
4828         // the second pretext is the mode (for example a light source)
4829         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4830         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4831         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4832         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4833         strlcat(cachename, modeinfo->name, sizeof(cachename));
4834
4835         // now add all the permutation pretexts
4836         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4837         {
4838                 if (permutation & (1<<i))
4839                 {
4840                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4841                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4842                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4843                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4844                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4845                 }
4846                 else
4847                 {
4848                         // keep line numbers correct
4849                         vertstrings_list[vertstrings_count++] = "\n";
4850                         geomstrings_list[geomstrings_count++] = "\n";
4851                         fragstrings_list[fragstrings_count++] = "\n";
4852                 }
4853         }
4854
4855         // replace spaces in the cachename with _ characters
4856         for (i = 0;cachename[i];i++)
4857                 if (cachename[i] == ' ')
4858                         cachename[i] = '_';
4859
4860         // now append the shader text itself
4861         vertstrings_list[vertstrings_count++] = vertexstring;
4862         geomstrings_list[geomstrings_count++] = geometrystring;
4863         fragstrings_list[fragstrings_count++] = fragmentstring;
4864
4865         // if any sources were NULL, clear the respective list
4866         if (!vertexstring)
4867                 vertstrings_count = 0;
4868         if (!geometrystring)
4869                 geomstrings_count = 0;
4870         if (!fragmentstring)
4871                 fragstrings_count = 0;
4872
4873         vertstring_length = 0;
4874         for (i = 0;i < vertstrings_count;i++)
4875                 vertstring_length += strlen(vertstrings_list[i]);
4876         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4877         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4878                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4879
4880         geomstring_length = 0;
4881         for (i = 0;i < geomstrings_count;i++)
4882                 geomstring_length += strlen(geomstrings_list[i]);
4883         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4884         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4885                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4886
4887         fragstring_length = 0;
4888         for (i = 0;i < fragstrings_count;i++)
4889                 fragstring_length += strlen(fragstrings_list[i]);
4890         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4891         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4892                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4893
4894         // try to load the cached shader, or generate one
4895         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4896
4897         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4898                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4899         else
4900                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4901
4902         // free the strings
4903         if (vertstring)
4904                 Mem_Free(vertstring);
4905         if (geomstring)
4906                 Mem_Free(geomstring);
4907         if (fragstring)
4908                 Mem_Free(fragstring);
4909         if (vertexstring)
4910                 Mem_Free(vertexstring);
4911         if (geometrystring)
4912                 Mem_Free(geometrystring);
4913         if (fragmentstring)
4914                 Mem_Free(fragmentstring);
4915 }
4916
4917 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4918 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4919 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);}
4920 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);}
4921 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);}
4922 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);}
4923
4924 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4925 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4926 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);}
4927 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);}
4928 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);}
4929 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);}
4930
4931 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4932 {
4933         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4934         if (r_hlsl_permutation != perm)
4935         {
4936                 r_hlsl_permutation = perm;
4937                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4938                 {
4939                         if (!r_hlsl_permutation->compiled)
4940                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4941                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4942                         {
4943                                 // remove features until we find a valid permutation
4944                                 int i;
4945                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4946                                 {
4947                                         // reduce i more quickly whenever it would not remove any bits
4948                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4949                                         if (!(permutation & j))
4950                                                 continue;
4951                                         permutation -= j;
4952                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4953                                         if (!r_hlsl_permutation->compiled)
4954                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4955                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4956                                                 break;
4957                                 }
4958                                 if (i >= SHADERPERMUTATION_COUNT)
4959                                 {
4960                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4961                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4962                                         return; // no bit left to clear, entire mode is broken
4963                                 }
4964                         }
4965                 }
4966                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4967                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4968         }
4969         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4970         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4971         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4972 }
4973 #endif
4974
4975 void R_GLSL_Restart_f(void)
4976 {
4977         unsigned int i, limit;
4978         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4979                 Mem_Free(glslshaderstring);
4980         glslshaderstring = NULL;
4981         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4982                 Mem_Free(cgshaderstring);
4983         cgshaderstring = NULL;
4984         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4985                 Mem_Free(hlslshaderstring);
4986         hlslshaderstring = NULL;
4987         switch(vid.renderpath)
4988         {
4989         case RENDERPATH_D3D9:
4990 #ifdef SUPPORTD3D
4991                 {
4992                         r_hlsl_permutation_t *p;
4993                         r_hlsl_permutation = NULL;
4994 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4995 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4996 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4997 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4998                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4999                         for (i = 0;i < limit;i++)
5000                         {
5001                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5002                                 {
5003                                         if (p->vertexshader)
5004                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5005                                         if (p->pixelshader)
5006                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5007                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5008                                 }
5009                         }
5010                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5011                 }
5012 #endif
5013                 break;
5014         case RENDERPATH_D3D10:
5015                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5016                 break;
5017         case RENDERPATH_D3D11:
5018                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5019                 break;
5020         case RENDERPATH_GL20:
5021                 {
5022                         r_glsl_permutation_t *p;
5023                         r_glsl_permutation = NULL;
5024                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5025                         for (i = 0;i < limit;i++)
5026                         {
5027                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5028                                 {
5029                                         GL_Backend_FreeProgram(p->program);
5030                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5031                                 }
5032                         }
5033                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5034                 }
5035                 break;
5036         case RENDERPATH_CGGL:
5037 #ifdef SUPPORTCG
5038                 {
5039                         r_cg_permutation_t *p;
5040                         r_cg_permutation = NULL;
5041                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5042                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5043                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5044                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5045                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5046                         for (i = 0;i < limit;i++)
5047                         {
5048                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5049                                 {
5050                                         if (p->vprogram)
5051                                                 cgDestroyProgram(p->vprogram);
5052                                         if (p->fprogram)
5053                                                 cgDestroyProgram(p->fprogram);
5054                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5055                                 }
5056                         }
5057                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5058                 }
5059 #endif
5060                 break;
5061         case RENDERPATH_GL13:
5062         case RENDERPATH_GL11:
5063                 break;
5064         }
5065 }
5066
5067 void R_GLSL_DumpShader_f(void)
5068 {
5069         int i;
5070         qfile_t *file;
5071
5072         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5073         if (file)
5074         {
5075                 FS_Print(file, "/* The engine may define the following macros:\n");
5076                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5077                 for (i = 0;i < SHADERMODE_COUNT;i++)
5078                         FS_Print(file, glslshadermodeinfo[i].pretext);
5079                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5080                         FS_Print(file, shaderpermutationinfo[i].pretext);
5081                 FS_Print(file, "*/\n");
5082                 FS_Print(file, builtinshaderstring);
5083                 FS_Close(file);
5084                 Con_Printf("glsl/default.glsl written\n");
5085         }
5086         else
5087                 Con_Printf("failed to write to glsl/default.glsl\n");
5088
5089 #ifdef SUPPORTCG
5090         file = FS_OpenRealFile("cg/default.cg", "w", false);
5091         if (file)
5092         {
5093                 FS_Print(file, "/* The engine may define the following macros:\n");
5094                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5095                 for (i = 0;i < SHADERMODE_COUNT;i++)
5096                         FS_Print(file, cgshadermodeinfo[i].pretext);
5097                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5098                         FS_Print(file, shaderpermutationinfo[i].pretext);
5099                 FS_Print(file, "*/\n");
5100                 FS_Print(file, builtincgshaderstring);
5101                 FS_Close(file);
5102                 Con_Printf("cg/default.cg written\n");
5103         }
5104         else
5105                 Con_Printf("failed to write to cg/default.cg\n");
5106 #endif
5107
5108 #ifdef SUPPORTD3D
5109         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5110         if (file)
5111         {
5112                 FS_Print(file, "/* The engine may define the following macros:\n");
5113                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5114                 for (i = 0;i < SHADERMODE_COUNT;i++)
5115                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5116                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5117                         FS_Print(file, shaderpermutationinfo[i].pretext);
5118                 FS_Print(file, "*/\n");
5119                 FS_Print(file, builtincgshaderstring);
5120                 FS_Close(file);
5121                 Con_Printf("hlsl/default.hlsl written\n");
5122         }
5123         else
5124                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5125 #endif
5126 }
5127
5128 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5129 {
5130         if (!second)
5131                 texturemode = GL_MODULATE;
5132         switch (vid.renderpath)
5133         {
5134         case RENDERPATH_D3D9:
5135 #ifdef SUPPORTD3D
5136                 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))));
5137                 R_Mesh_TexBind(GL20TU_FIRST , first );
5138                 R_Mesh_TexBind(GL20TU_SECOND, second);
5139 #endif
5140                 break;
5141         case RENDERPATH_D3D10:
5142                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5143                 break;
5144         case RENDERPATH_D3D11:
5145                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5146                 break;
5147         case RENDERPATH_GL20:
5148                 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))));
5149                 R_Mesh_TexBind(GL20TU_FIRST , first );
5150                 R_Mesh_TexBind(GL20TU_SECOND, second);
5151                 break;
5152         case RENDERPATH_CGGL:
5153 #ifdef SUPPORTCG
5154                 CHECKCGERROR
5155                 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))));
5156                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5157                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5158 #endif
5159                 break;
5160         case RENDERPATH_GL13:
5161                 R_Mesh_TexBind(0, first );
5162                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5163                 R_Mesh_TexBind(1, second);
5164                 if (second)
5165                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5166                 break;
5167         case RENDERPATH_GL11:
5168                 R_Mesh_TexBind(0, first );
5169                 break;
5170         }
5171 }
5172
5173 void R_SetupShader_DepthOrShadow(void)
5174 {
5175         switch (vid.renderpath)
5176         {
5177         case RENDERPATH_D3D9:
5178 #ifdef SUPPORTD3D
5179                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5180 #endif
5181                 break;
5182         case RENDERPATH_D3D10:
5183                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5184                 break;
5185         case RENDERPATH_D3D11:
5186                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5187                 break;
5188         case RENDERPATH_GL20:
5189                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5190                 break;
5191         case RENDERPATH_CGGL:
5192 #ifdef SUPPORTCG
5193                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5194 #endif
5195                 break;
5196         case RENDERPATH_GL13:
5197                 R_Mesh_TexBind(0, 0);
5198                 R_Mesh_TexBind(1, 0);
5199                 break;
5200         case RENDERPATH_GL11:
5201                 R_Mesh_TexBind(0, 0);
5202                 break;
5203         }
5204 }
5205
5206 void R_SetupShader_ShowDepth(void)
5207 {
5208         switch (vid.renderpath)
5209         {
5210         case RENDERPATH_D3D9:
5211 #ifdef SUPPORTHLSL
5212                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5213 #endif
5214                 break;
5215         case RENDERPATH_D3D10:
5216                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5217                 break;
5218         case RENDERPATH_D3D11:
5219                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5220                 break;
5221         case RENDERPATH_GL20:
5222                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5223                 break;
5224         case RENDERPATH_CGGL:
5225 #ifdef SUPPORTCG
5226                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5227 #endif
5228                 break;
5229         case RENDERPATH_GL13:
5230                 break;
5231         case RENDERPATH_GL11:
5232                 break;
5233         }
5234 }
5235
5236 extern qboolean r_shadow_usingdeferredprepass;
5237 extern cvar_t r_shadow_deferred_8bitrange;
5238 extern rtexture_t *r_shadow_attenuationgradienttexture;
5239 extern rtexture_t *r_shadow_attenuation2dtexture;
5240 extern rtexture_t *r_shadow_attenuation3dtexture;
5241 extern qboolean r_shadow_usingshadowmaprect;
5242 extern qboolean r_shadow_usingshadowmapcube;
5243 extern qboolean r_shadow_usingshadowmap2d;
5244 extern qboolean r_shadow_usingshadowmaportho;
5245 extern float r_shadow_shadowmap_texturescale[2];
5246 extern float r_shadow_shadowmap_parameters[4];
5247 extern qboolean r_shadow_shadowmapvsdct;
5248 extern qboolean r_shadow_shadowmapsampler;
5249 extern int r_shadow_shadowmappcf;
5250 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5251 extern rtexture_t *r_shadow_shadowmap2dtexture;
5252 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5253 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5254 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5255 extern matrix4x4_t r_shadow_shadowmapmatrix;
5256 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5257 extern int r_shadow_prepass_width;
5258 extern int r_shadow_prepass_height;
5259 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5260 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5261 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5262 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5263 extern cvar_t gl_mesh_separatearrays;
5264 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5265 {
5266         // a blendfunc allows colormod if:
5267         // a) it can never keep the destination pixel invariant, or
5268         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5269         // this is to prevent unintended side effects from colormod
5270
5271         // in formulas:
5272         // IF there is a (s, sa) for which for all (d, da),
5273         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5274         // THEN, for this (s, sa) and all (colormod, d, da):
5275         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5276         // OBVIOUSLY, this means that
5277         //   s*colormod * src(s*colormod, d, sa, da) = 0
5278         //   dst(s*colormod, d, sa, da)              = 1
5279
5280         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5281
5282         // main condition to leave dst color invariant:
5283         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5284         //   src == GL_ZERO:
5285         //     s * 0 + d * dst(s, d, sa, da) == d
5286         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5287         //       => colormod is a problem for GL_SRC_COLOR only
5288         //   src == GL_ONE:
5289         //     s + d * dst(s, d, sa, da) == d
5290         //       => s == 0
5291         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5292         //       => colormod is never problematic for these
5293         //   src == GL_SRC_COLOR:
5294         //     s*s + d * dst(s, d, sa, da) == d
5295         //       => s == 0
5296         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5297         //       => colormod is never problematic for these
5298         //   src == GL_ONE_MINUS_SRC_COLOR:
5299         //     s*(1-s) + d * dst(s, d, sa, da) == d
5300         //       => s == 0 or s == 1
5301         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is a problem for GL_SRC_COLOR only
5303         //   src == GL_DST_COLOR
5304         //     s*d + d * dst(s, d, sa, da) == d
5305         //       => s == 1
5306         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod is always a problem
5308         //     or
5309         //       => s == 0
5310         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod is never problematic for these
5312         //       => BUT, we do not know s! We must assume it is problematic
5313         //       then... except in GL_ONE case, where we know all invariant
5314         //       cases are fine
5315         //   src == GL_ONE_MINUS_DST_COLOR
5316         //     s*(1-d) + d * dst(s, d, sa, da) == d
5317         //       => s == 0 (1-d is impossible to handle for our desired result)
5318         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5319         //       => colormod is never problematic for these
5320         //   src == GL_SRC_ALPHA
5321         //     s*sa + d * dst(s, d, sa, da) == d
5322         //       => s == 0, or sa == 0
5323         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5324         //       => colormod breaks in the case GL_SRC_COLOR only
5325         //   src == GL_ONE_MINUS_SRC_ALPHA
5326         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5327         //       => s == 0, or sa == 1
5328         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5329         //       => colormod breaks in the case GL_SRC_COLOR only
5330         //   src == GL_DST_ALPHA
5331         //     s*da + d * dst(s, d, sa, da) == d
5332         //       => s == 0
5333         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334         //       => colormod is never problematic for these
5335
5336         switch(src)
5337         {
5338                 case GL_ZERO:
5339                 case GL_ONE_MINUS_SRC_COLOR:
5340                 case GL_SRC_ALPHA:
5341                 case GL_ONE_MINUS_SRC_ALPHA:
5342                         if(dst == GL_SRC_COLOR)
5343                                 return false;
5344                         return true;
5345                 case GL_ONE:
5346                 case GL_SRC_COLOR:
5347                 case GL_ONE_MINUS_DST_COLOR:
5348                 case GL_DST_ALPHA:
5349                 case GL_ONE_MINUS_DST_ALPHA:
5350                         return true;
5351                 case GL_DST_COLOR:
5352                         if(dst == GL_ONE)
5353                                 return true;
5354                         return false;
5355                 default:
5356                         return false;
5357         }
5358 }
5359 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)
5360 {
5361         // select a permutation of the lighting shader appropriate to this
5362         // combination of texture, entity, light source, and fogging, only use the
5363         // minimum features necessary to avoid wasting rendering time in the
5364         // fragment shader on features that are not being used
5365         unsigned int permutation = 0;
5366         unsigned int mode = 0;
5367         qboolean allow_colormod;
5368         static float dummy_colormod[3] = {1, 1, 1};
5369         float *colormod = rsurface.colormod;
5370         float m16f[16];
5371         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5372         if (rsurfacepass == RSURFPASS_BACKGROUND)
5373         {
5374                 // distorted background
5375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5376                         mode = SHADERMODE_WATER;
5377                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5378                         mode = SHADERMODE_REFRACTION;
5379                 else
5380                 {
5381                         mode = SHADERMODE_GENERIC;
5382                         permutation |= SHADERPERMUTATION_DIFFUSE;
5383                 }
5384                 GL_AlphaTest(false);
5385                 GL_BlendFunc(GL_ONE, GL_ZERO);
5386                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5387         }
5388         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5389         {
5390                 if (r_glsl_offsetmapping.integer)
5391                 {
5392                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5393                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5394                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5395                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5396                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5397                         {
5398                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5399                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5400                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5401                         }
5402                 }
5403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5404                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5405                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5406                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5407                 // normalmap (deferred prepass), may use alpha test on diffuse
5408                 mode = SHADERMODE_DEFERREDGEOMETRY;
5409                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5410                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5411                 GL_AlphaTest(false);
5412                 GL_BlendFunc(GL_ONE, GL_ZERO);
5413                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5414         }
5415         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5416         {
5417                 if (r_glsl_offsetmapping.integer)
5418                 {
5419                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5420                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5421                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5422                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5423                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5424                         {
5425                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5426                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5427                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5428                         }
5429                 }
5430                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5431                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5432                 // light source
5433                 mode = SHADERMODE_LIGHTSOURCE;
5434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5435                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5436                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5437                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5438                 if (diffusescale > 0)
5439                         permutation |= SHADERPERMUTATION_DIFFUSE;
5440                 if (specularscale > 0)
5441                 {
5442                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5443                         if (r_shadow_glossexact.integer)
5444                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5445                 }
5446                 if (r_refdef.fogenabled)
5447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5448                 if (rsurface.texture->colormapping)
5449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5450                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5451                 {
5452                         if (r_shadow_usingshadowmaprect)
5453                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5454                         if (r_shadow_usingshadowmap2d)
5455                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5456                         if (r_shadow_usingshadowmapcube)
5457                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5458                         else if(r_shadow_shadowmapvsdct)
5459                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5460
5461                         if (r_shadow_shadowmapsampler)
5462                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5463                         if (r_shadow_shadowmappcf > 1)
5464                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5465                         else if (r_shadow_shadowmappcf)
5466                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5467                 }
5468                 if (rsurface.texture->reflectmasktexture)
5469                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5470                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5471                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5472                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5473         }
5474         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5475         {
5476                 if (r_glsl_offsetmapping.integer)
5477                 {
5478                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5479                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5480                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5481                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5482                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5483                         {
5484                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5485                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5486                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5487                         }
5488                 }
5489                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5490                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5491                 // unshaded geometry (fullbright or ambient model lighting)
5492                 mode = SHADERMODE_FLATCOLOR;
5493                 ambientscale = diffusescale = specularscale = 0;
5494                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5495                         permutation |= SHADERPERMUTATION_GLOW;
5496                 if (r_refdef.fogenabled)
5497                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5498                 if (rsurface.texture->colormapping)
5499                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5500                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5501                 {
5502                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5503                         if (r_shadow_usingshadowmaprect)
5504                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5505                         if (r_shadow_usingshadowmap2d)
5506                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5507
5508                         if (r_shadow_shadowmapsampler)
5509                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5510                         if (r_shadow_shadowmappcf > 1)
5511                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5512                         else if (r_shadow_shadowmappcf)
5513                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5514                 }
5515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5516                         permutation |= SHADERPERMUTATION_REFLECTION;
5517                 if (rsurface.texture->reflectmasktexture)
5518                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5519                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5520                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5521                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5522         }
5523         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5524         {
5525                 if (r_glsl_offsetmapping.integer)
5526                 {
5527                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5528                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5529                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5530                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5531                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5532                         {
5533                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5534                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5535                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5536                         }
5537                 }
5538                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5539                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5540                 // directional model lighting
5541                 mode = SHADERMODE_LIGHTDIRECTION;
5542                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5543                         permutation |= SHADERPERMUTATION_GLOW;
5544                 permutation |= SHADERPERMUTATION_DIFFUSE;
5545                 if (specularscale > 0)
5546                 {
5547                         permutation |= SHADERPERMUTATION_SPECULAR;
5548                         if (r_shadow_glossexact.integer)
5549                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5550                 }
5551                 if (r_refdef.fogenabled)
5552                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5553                 if (rsurface.texture->colormapping)
5554                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5555                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5556                 {
5557                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5558                         if (r_shadow_usingshadowmaprect)
5559                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5560                         if (r_shadow_usingshadowmap2d)
5561                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5562
5563                         if (r_shadow_shadowmapsampler)
5564                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5565                         if (r_shadow_shadowmappcf > 1)
5566                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5567                         else if (r_shadow_shadowmappcf)
5568                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5569                 }
5570                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5571                         permutation |= SHADERPERMUTATION_REFLECTION;
5572                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5573                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5574                 if (rsurface.texture->reflectmasktexture)
5575                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5576                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5577                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5578                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5579         }
5580         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5581         {
5582                 if (r_glsl_offsetmapping.integer)
5583                 {
5584                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5585                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5586                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5587                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5588                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5589                         {
5590                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5591                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5592                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5593                         }
5594                 }
5595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5596                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5597                 // ambient model lighting
5598                 mode = SHADERMODE_LIGHTDIRECTION;
5599                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5600                         permutation |= SHADERPERMUTATION_GLOW;
5601                 if (r_refdef.fogenabled)
5602                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5603                 if (rsurface.texture->colormapping)
5604                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5605                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5606                 {
5607                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5608                         if (r_shadow_usingshadowmaprect)
5609                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5610                         if (r_shadow_usingshadowmap2d)
5611                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5612
5613                         if (r_shadow_shadowmapsampler)
5614                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5615                         if (r_shadow_shadowmappcf > 1)
5616                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5617                         else if (r_shadow_shadowmappcf)
5618                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5619                 }
5620                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5621                         permutation |= SHADERPERMUTATION_REFLECTION;
5622                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5623                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5624                 if (rsurface.texture->reflectmasktexture)
5625                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5626                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5627                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5628                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5629         }
5630         else
5631         {
5632                 if (r_glsl_offsetmapping.integer)
5633                 {
5634                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5635                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5636                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5638                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5639                         {
5640                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5641                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5642                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5643                         }
5644                 }
5645                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5646                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5647                 // lightmapped wall
5648                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5649                         permutation |= SHADERPERMUTATION_GLOW;
5650                 if (r_refdef.fogenabled)
5651                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5652                 if (rsurface.texture->colormapping)
5653                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5654                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5655                 {
5656                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5657                         if (r_shadow_usingshadowmaprect)
5658                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5659                         if (r_shadow_usingshadowmap2d)
5660                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5661
5662                         if (r_shadow_shadowmapsampler)
5663                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5664                         if (r_shadow_shadowmappcf > 1)
5665                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5666                         else if (r_shadow_shadowmappcf)
5667                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5668                 }
5669                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5670                         permutation |= SHADERPERMUTATION_REFLECTION;
5671                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5672                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5673                 if (rsurface.texture->reflectmasktexture)
5674                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5675                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5676                 {
5677                         // deluxemapping (light direction texture)
5678                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5679                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5680                         else
5681                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5682                         permutation |= SHADERPERMUTATION_DIFFUSE;
5683                         if (specularscale > 0)
5684                         {
5685                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5686                                 if (r_shadow_glossexact.integer)
5687                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5688                         }
5689                 }
5690                 else if (r_glsl_deluxemapping.integer >= 2)
5691                 {
5692                         // fake deluxemapping (uniform light direction in tangentspace)
5693                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5694                         permutation |= SHADERPERMUTATION_DIFFUSE;
5695                         if (specularscale > 0)
5696                         {
5697                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5698                                 if (r_shadow_glossexact.integer)
5699                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5700                         }
5701                 }
5702                 else if (rsurface.uselightmaptexture)
5703                 {
5704                         // ordinary lightmapping (q1bsp, q3bsp)
5705                         mode = SHADERMODE_LIGHTMAP;
5706                 }
5707                 else
5708                 {
5709                         // ordinary vertex coloring (q3bsp)
5710                         mode = SHADERMODE_VERTEXCOLOR;
5711                 }
5712                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5713                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5714                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5715         }
5716         if(!allow_colormod)
5717                 colormod = dummy_colormod;
5718         switch(vid.renderpath)
5719         {
5720         case RENDERPATH_D3D9:
5721 #ifdef SUPPORTD3D
5722                 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);
5723                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5724                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5725                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5726                 if (mode == SHADERMODE_LIGHTSOURCE)
5727                 {
5728                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5729                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5730                 }
5731                 else
5732                 {
5733                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5734                         {
5735                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5736                         }
5737                 }
5738                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5739                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5740                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5741                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5742                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5743
5744                 if (mode == SHADERMODE_LIGHTSOURCE)
5745                 {
5746                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5747                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5749                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5750                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5751
5752                         // additive passes are only darkened by fog, not tinted
5753                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5754                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5755                 }
5756                 else
5757                 {
5758                         if (mode == SHADERMODE_FLATCOLOR)
5759                         {
5760                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5761                         }
5762                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5763                         {
5764                                 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]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5766                                 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);
5767                                 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);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5770                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5771                         }
5772                         else
5773                         {
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5775                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5776                                 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);
5777                                 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);
5778                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5779                         }
5780                         // additive passes are only darkened by fog, not tinted
5781                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5782                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5783                         else
5784                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5785                         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);
5786                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5788                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5789                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5790                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5791                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5792                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5793                 }
5794                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5795                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5796                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5797                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5798                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5799                 if (rsurface.texture->pantstexture)
5800                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5801                 else
5802                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5803                 if (rsurface.texture->shirttexture)
5804                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5805                 else
5806                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5807                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5808                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5809                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5810                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5812                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5813                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5814
5815                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5816                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5817                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5818                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5819                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5823                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5825                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5827                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5828                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5829                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5830                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5831                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5832                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5833                 {
5834                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5835                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5836                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5837                 }
5838                 else
5839                 {
5840                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5841                 }
5842 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5844                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5846                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5847                 {
5848                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5849                         if (rsurface.rtlight)
5850                         {
5851                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5852                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5853                         }
5854                 }
5855 #endif
5856                 break;
5857         case RENDERPATH_D3D10:
5858                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5859                 break;
5860         case RENDERPATH_D3D11:
5861                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5862                 break;
5863         case RENDERPATH_GL20:
5864                 if (gl_mesh_separatearrays.integer)
5865                 {
5866                         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);
5867                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5868                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5869                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5870                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5871                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5872                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5874                 }
5875                 else
5876                 {
5877                         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);
5878                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5879                 }
5880                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5881                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5882                 if (mode == SHADERMODE_LIGHTSOURCE)
5883                 {
5884                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5885                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5886                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5887                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5888                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5889                         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);
5890         
5891                         // additive passes are only darkened by fog, not tinted
5892                         if (r_glsl_permutation->loc_FogColor >= 0)
5893                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5894                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5895                 }
5896                 else
5897                 {
5898                         if (mode == SHADERMODE_FLATCOLOR)
5899                         {
5900                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5901                         }
5902                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5903                         {
5904                                 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]);
5905                                 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]);
5906                                 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);
5907                                 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);
5908                                 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);
5909                                 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]);
5910                                 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]);
5911                         }
5912                         else
5913                         {
5914                                 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]);
5915                                 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]);
5916                                 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);
5917                                 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);
5918                                 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);
5919                         }
5920                         // additive passes are only darkened by fog, not tinted
5921                         if (r_glsl_permutation->loc_FogColor >= 0)
5922                         {
5923                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5924                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5925                                 else
5926                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5927                         }
5928                         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);
5929                         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]);
5930                         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]);
5931                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5932                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5933                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5934                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5935                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5936                 }
5937                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5938                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5939                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5940                 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]);
5941                 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]);
5942
5943                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5944                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5945                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5946                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5947                 {
5948                         if (rsurface.texture->pantstexture)
5949                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5950                         else
5951                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5952                 }
5953                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5954                 {
5955                         if (rsurface.texture->shirttexture)
5956                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5957                         else
5958                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5959                 }
5960                 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]);
5961                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5962                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5963                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5964                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5965                 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]);
5966                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5967
5968         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5969         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5970         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5971                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5972                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5973                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5974                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5975                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5976                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5977                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5978                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5979                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5980                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5981                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5982                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5983                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5984                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5985                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5986                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5987                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5988                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5989                 {
5990                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5991                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5992                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5993                 }
5994                 else
5995                 {
5996                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5997                 }
5998 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5999 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6000                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6001                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6002                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6003                 {
6004                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6005                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
6006                         if (rsurface.rtlight)
6007                         {
6008                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6009                                 if (r_shadow_usingshadowmapcube)
6010                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6011                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6012                         }
6013                 }
6014                 CHECKGLERROR
6015                 break;
6016         case RENDERPATH_CGGL:
6017 #ifdef SUPPORTCG
6018                 if (gl_mesh_separatearrays.integer)
6019                 {
6020                         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);
6021                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6022                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6023                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6024                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6026                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6027                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6028                 }
6029                 else
6030                 {
6031                         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);
6032                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6033                 }
6034                 R_SetupShader_SetPermutationCG(mode, permutation);
6035                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6036                 if (mode == SHADERMODE_LIGHTSOURCE)
6037                 {
6038                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6039                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6040                 }
6041                 else
6042                 {
6043                         if (mode == SHADERMODE_LIGHTDIRECTION)
6044                         {
6045                                 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
6046                         }
6047                 }
6048                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6049                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6050                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6051                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6052                 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
6053                 CHECKGLERROR
6054
6055                 if (mode == SHADERMODE_LIGHTSOURCE)
6056                 {
6057                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6058                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6059                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6060                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6061                         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
6062
6063                         // additive passes are only darkened by fog, not tinted
6064                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6065                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6066                 }
6067                 else
6068                 {
6069                         if (mode == SHADERMODE_FLATCOLOR)
6070                         {
6071                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6072                         }
6073                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6074                         {
6075                                 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
6076                                 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
6077                                 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
6078                                 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
6079                                 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
6080                                 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
6081                                 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
6082                         }
6083                         else
6084                         {
6085                                 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
6086                                 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
6087                                 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
6088                                 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
6089                                 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
6090                         }
6091                         // additive passes are only darkened by fog, not tinted
6092                         if (r_cg_permutation->fp_FogColor)
6093                         {
6094                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6095                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6096                                 else
6097                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6098                                 CHECKCGERROR
6099                         }
6100                         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
6101                         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
6102                         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
6103                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6104                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6105                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6106                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6107                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6108                 }
6109                 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
6110                 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
6111                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6112                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6113                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6114                 if (r_cg_permutation->fp_Color_Pants)
6115                 {
6116                         if (rsurface.texture->pantstexture)
6117                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6118                         else
6119                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6120                         CHECKCGERROR
6121                 }
6122                 if (r_cg_permutation->fp_Color_Shirt)
6123                 {
6124                         if (rsurface.texture->shirttexture)
6125                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6126                         else
6127                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6128                         CHECKCGERROR
6129                 }
6130                 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
6131                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6132                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6133                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6134                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6135                 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
6136                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6137
6138         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6139         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6140         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6151                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6152                 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
6153                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6158                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6159                 {
6160                         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
6161                         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
6162                         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
6163                 }
6164                 else
6165                 {
6166                         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
6167                 }
6168                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6169                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6170                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6171                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6172                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6173                 {
6174                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6175                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6176                         if (rsurface.rtlight)
6177                         {
6178                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6179                                 if (r_shadow_usingshadowmapcube)
6180                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6181                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6182                         }
6183                 }
6184
6185                 CHECKGLERROR
6186 #endif
6187                 break;
6188         case RENDERPATH_GL13:
6189         case RENDERPATH_GL11:
6190                 break;
6191         }
6192 }
6193
6194 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6195 {
6196         // select a permutation of the lighting shader appropriate to this
6197         // combination of texture, entity, light source, and fogging, only use the
6198         // minimum features necessary to avoid wasting rendering time in the
6199         // fragment shader on features that are not being used
6200         unsigned int permutation = 0;
6201         unsigned int mode = 0;
6202         const float *lightcolorbase = rtlight->currentcolor;
6203         float ambientscale = rtlight->ambientscale;
6204         float diffusescale = rtlight->diffusescale;
6205         float specularscale = rtlight->specularscale;
6206         // this is the location of the light in view space
6207         vec3_t viewlightorigin;
6208         // this transforms from view space (camera) to light space (cubemap)
6209         matrix4x4_t viewtolight;
6210         matrix4x4_t lighttoview;
6211         float viewtolight16f[16];
6212         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6213         // light source
6214         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6215         if (rtlight->currentcubemap != r_texture_whitecube)
6216                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6217         if (diffusescale > 0)
6218                 permutation |= SHADERPERMUTATION_DIFFUSE;
6219         if (specularscale > 0)
6220         {
6221                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6222                 if (r_shadow_glossexact.integer)
6223                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6224         }
6225         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6226         {
6227                 if (r_shadow_usingshadowmaprect)
6228                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6229                 if (r_shadow_usingshadowmap2d)
6230                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6231                 if (r_shadow_usingshadowmapcube)
6232                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6233                 else if(r_shadow_shadowmapvsdct)
6234                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6235
6236                 if (r_shadow_shadowmapsampler)
6237                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6238                 if (r_shadow_shadowmappcf > 1)
6239                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6240                 else if (r_shadow_shadowmappcf)
6241                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6242         }
6243         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6244         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6245         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6246         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6247         switch(vid.renderpath)
6248         {
6249         case RENDERPATH_D3D9:
6250 #ifdef SUPPORTD3D
6251                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6252                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6253                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6254                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6255                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6256                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6257                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6258                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6259                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6260                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6261                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6262
6263                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6264                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6265                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6266                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6267                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6268                 if (r_shadow_usingshadowmapcube)
6269                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6270                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6271                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6272 #endif
6273                 break;
6274         case RENDERPATH_D3D10:
6275                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6276                 break;
6277         case RENDERPATH_D3D11:
6278                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6279                 break;
6280         case RENDERPATH_GL20:
6281                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6282                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6283                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6284                 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);
6285                 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);
6286                 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);
6287                 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]);
6288                 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]);
6289                 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));
6290                 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]);
6291                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6292
6293                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6294                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6295                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6296                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6297                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6298                 if (r_shadow_usingshadowmapcube)
6299                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6300                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6301                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6302                 break;
6303         case RENDERPATH_CGGL:
6304 #ifdef SUPPORTCG
6305                 R_SetupShader_SetPermutationCG(mode, permutation);
6306                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6307                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6308                 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
6309                 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
6310                 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
6311                 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
6312                 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
6313                 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
6314                 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
6315                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6316
6317                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6318                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6319                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6320                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6321                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6322                 if (r_shadow_usingshadowmapcube)
6323                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6324                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6325                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6326 #endif
6327                 break;
6328         case RENDERPATH_GL13:
6329         case RENDERPATH_GL11:
6330                 break;
6331         }
6332 }
6333
6334 #define SKINFRAME_HASH 1024
6335
6336 typedef struct
6337 {
6338         int loadsequence; // incremented each level change
6339         memexpandablearray_t array;
6340         skinframe_t *hash[SKINFRAME_HASH];
6341 }
6342 r_skinframe_t;
6343 r_skinframe_t r_skinframe;
6344
6345 void R_SkinFrame_PrepareForPurge(void)
6346 {
6347         r_skinframe.loadsequence++;
6348         // wrap it without hitting zero
6349         if (r_skinframe.loadsequence >= 200)
6350                 r_skinframe.loadsequence = 1;
6351 }
6352
6353 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6354 {
6355         if (!skinframe)
6356                 return;
6357         // mark the skinframe as used for the purging code
6358         skinframe->loadsequence = r_skinframe.loadsequence;
6359 }
6360
6361 void R_SkinFrame_Purge(void)
6362 {
6363         int i;
6364         skinframe_t *s;
6365         for (i = 0;i < SKINFRAME_HASH;i++)
6366         {
6367                 for (s = r_skinframe.hash[i];s;s = s->next)
6368                 {
6369                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6370                         {
6371                                 if (s->merged == s->base)
6372                                         s->merged = NULL;
6373                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6374                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6375                                 R_PurgeTexture(s->merged);s->merged = NULL;
6376                                 R_PurgeTexture(s->base  );s->base   = NULL;
6377                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6378                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6379                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6380                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6381                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6382                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6383                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6384                                 s->loadsequence = 0;
6385                         }
6386                 }
6387         }
6388 }
6389
6390 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6391         skinframe_t *item;
6392         char basename[MAX_QPATH];
6393
6394         Image_StripImageExtension(name, basename, sizeof(basename));
6395
6396         if( last == NULL ) {
6397                 int hashindex;
6398                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6399                 item = r_skinframe.hash[hashindex];
6400         } else {
6401                 item = last->next;
6402         }
6403
6404         // linearly search through the hash bucket
6405         for( ; item ; item = item->next ) {
6406                 if( !strcmp( item->basename, basename ) ) {
6407                         return item;
6408                 }
6409         }
6410         return NULL;
6411 }
6412
6413 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6414 {
6415         skinframe_t *item;
6416         int hashindex;
6417         char basename[MAX_QPATH];
6418
6419         Image_StripImageExtension(name, basename, sizeof(basename));
6420
6421         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6422         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6423                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6424                         break;
6425
6426         if (!item) {
6427                 rtexture_t *dyntexture;
6428                 // check whether its a dynamic texture
6429                 dyntexture = CL_GetDynTexture( basename );
6430                 if (!add && !dyntexture)
6431                         return NULL;
6432                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6433                 memset(item, 0, sizeof(*item));
6434                 strlcpy(item->basename, basename, sizeof(item->basename));
6435                 item->base = dyntexture; // either NULL or dyntexture handle
6436                 item->textureflags = textureflags;
6437                 item->comparewidth = comparewidth;
6438                 item->compareheight = compareheight;
6439                 item->comparecrc = comparecrc;
6440                 item->next = r_skinframe.hash[hashindex];
6441                 r_skinframe.hash[hashindex] = item;
6442         }
6443         else if( item->base == NULL )
6444         {
6445                 rtexture_t *dyntexture;
6446                 // check whether its a dynamic texture
6447                 // 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]
6448                 dyntexture = CL_GetDynTexture( basename );
6449                 item->base = dyntexture; // either NULL or dyntexture handle
6450         }
6451
6452         R_SkinFrame_MarkUsed(item);
6453         return item;
6454 }
6455
6456 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6457         { \
6458                 unsigned long long avgcolor[5], wsum; \
6459                 int pix, comp, w; \
6460                 avgcolor[0] = 0; \
6461                 avgcolor[1] = 0; \
6462                 avgcolor[2] = 0; \
6463                 avgcolor[3] = 0; \
6464                 avgcolor[4] = 0; \
6465                 wsum = 0; \
6466                 for(pix = 0; pix < cnt; ++pix) \
6467                 { \
6468                         w = 0; \
6469                         for(comp = 0; comp < 3; ++comp) \
6470                                 w += getpixel; \
6471                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6472                         { \
6473                                 ++wsum; \
6474                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6475                                 w = getpixel; \
6476                                 for(comp = 0; comp < 3; ++comp) \
6477                                         avgcolor[comp] += getpixel * w; \
6478                                 avgcolor[3] += w; \
6479                         } \
6480                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6481                         avgcolor[4] += getpixel; \
6482                 } \
6483                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6484                         avgcolor[3] = 1; \
6485                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6486                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6487                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6488                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6489         }
6490
6491 extern cvar_t gl_picmip;
6492 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6493 {
6494         int j;
6495         unsigned char *pixels;
6496         unsigned char *bumppixels;
6497         unsigned char *basepixels = NULL;
6498         int basepixels_width = 0;
6499         int basepixels_height = 0;
6500         skinframe_t *skinframe;
6501         rtexture_t *ddsbase = NULL;
6502         qboolean ddshasalpha = false;
6503         float ddsavgcolor[4];
6504         char basename[MAX_QPATH];
6505         int miplevel = R_PicmipForFlags(textureflags);
6506         int savemiplevel = miplevel;
6507         int mymiplevel;
6508
6509         if (cls.state == ca_dedicated)
6510                 return NULL;
6511
6512         // return an existing skinframe if already loaded
6513         // if loading of the first image fails, don't make a new skinframe as it
6514         // would cause all future lookups of this to be missing
6515         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6516         if (skinframe && skinframe->base)
6517                 return skinframe;
6518
6519         Image_StripImageExtension(name, basename, sizeof(basename));
6520
6521         // check for DDS texture file first
6522         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6523         {
6524                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6525                 if (basepixels == NULL)
6526                         return NULL;
6527         }
6528
6529         // FIXME handle miplevel
6530
6531         if (developer_loading.integer)
6532                 Con_Printf("loading skin \"%s\"\n", name);
6533
6534         // we've got some pixels to store, so really allocate this new texture now
6535         if (!skinframe)
6536                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6537         skinframe->stain = NULL;
6538         skinframe->merged = NULL;
6539         skinframe->base = NULL;
6540         skinframe->pants = NULL;
6541         skinframe->shirt = NULL;
6542         skinframe->nmap = NULL;
6543         skinframe->gloss = NULL;
6544         skinframe->glow = NULL;
6545         skinframe->fog = NULL;
6546         skinframe->reflect = NULL;
6547         skinframe->hasalpha = false;
6548
6549         if (ddsbase)
6550         {
6551                 skinframe->base = ddsbase;
6552                 skinframe->hasalpha = ddshasalpha;
6553                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6554                 if (r_loadfog && skinframe->hasalpha)
6555                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6556                 //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]);
6557         }
6558         else
6559         {
6560                 basepixels_width = image_width;
6561                 basepixels_height = image_height;
6562                 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);
6563                 if (textureflags & TEXF_ALPHA)
6564                 {
6565                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6566                         {
6567                                 if (basepixels[j] < 255)
6568                                 {
6569                                         skinframe->hasalpha = true;
6570                                         break;
6571                                 }
6572                         }
6573                         if (r_loadfog && skinframe->hasalpha)
6574                         {
6575                                 // has transparent pixels
6576                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6577                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6578                                 {
6579                                         pixels[j+0] = 255;
6580                                         pixels[j+1] = 255;
6581                                         pixels[j+2] = 255;
6582                                         pixels[j+3] = basepixels[j+3];
6583                                 }
6584                                 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);
6585                                 Mem_Free(pixels);
6586                         }
6587                 }
6588                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6589                 //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]);
6590                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6591                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6592                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6593                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6594         }
6595
6596         if (r_loaddds)
6597         {
6598                 mymiplevel = savemiplevel;
6599                 if (r_loadnormalmap)
6600                         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);
6601                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6602                 if (r_loadgloss)
6603                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6604                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6605                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6606                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6607         }
6608
6609         // _norm is the name used by tenebrae and has been adopted as standard
6610         if (r_loadnormalmap && skinframe->nmap == NULL)
6611         {
6612                 mymiplevel = savemiplevel;
6613                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6614                 {
6615                         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);
6616                         Mem_Free(pixels);
6617                         pixels = NULL;
6618                 }
6619                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6620                 {
6621                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6622                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6623                         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);
6624                         Mem_Free(pixels);
6625                         Mem_Free(bumppixels);
6626                 }
6627                 else if (r_shadow_bumpscale_basetexture.value > 0)
6628                 {
6629                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6630                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6631                         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);
6632                         Mem_Free(pixels);
6633                 }
6634                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6635                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6636         }
6637
6638         // _luma is supported only for tenebrae compatibility
6639         // _glow is the preferred name
6640         mymiplevel = savemiplevel;
6641         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))))
6642         {
6643                 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);
6644                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6645                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6646                 Mem_Free(pixels);pixels = NULL;
6647         }
6648
6649         mymiplevel = savemiplevel;
6650         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651         {
6652                 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);
6653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6654                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6655                 Mem_Free(pixels);
6656                 pixels = NULL;
6657         }
6658
6659         mymiplevel = savemiplevel;
6660         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6661         {
6662                 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);
6663                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6664                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6665                 Mem_Free(pixels);
6666                 pixels = NULL;
6667         }
6668
6669         mymiplevel = savemiplevel;
6670         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6671         {
6672                 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);
6673                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6674                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6675                 Mem_Free(pixels);
6676                 pixels = NULL;
6677         }
6678
6679         mymiplevel = savemiplevel;
6680         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6681         {
6682                 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);
6683                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6684                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6685                 Mem_Free(pixels);
6686                 pixels = NULL;
6687         }
6688
6689         if (basepixels)
6690                 Mem_Free(basepixels);
6691
6692         return skinframe;
6693 }
6694
6695 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6696 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6697 {
6698         int i;
6699         unsigned char *temp1, *temp2;
6700         skinframe_t *skinframe;
6701
6702         if (cls.state == ca_dedicated)
6703                 return NULL;
6704
6705         // if already loaded just return it, otherwise make a new skinframe
6706         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6707         if (skinframe && skinframe->base)
6708                 return skinframe;
6709
6710         skinframe->stain = NULL;
6711         skinframe->merged = NULL;
6712         skinframe->base = NULL;
6713         skinframe->pants = NULL;
6714         skinframe->shirt = NULL;
6715         skinframe->nmap = NULL;
6716         skinframe->gloss = NULL;
6717         skinframe->glow = NULL;
6718         skinframe->fog = NULL;
6719         skinframe->reflect = NULL;
6720         skinframe->hasalpha = false;
6721
6722         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6723         if (!skindata)
6724                 return NULL;
6725
6726         if (developer_loading.integer)
6727                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6728
6729         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6730         {
6731                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6732                 temp2 = temp1 + width * height * 4;
6733                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6734                 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);
6735                 Mem_Free(temp1);
6736         }
6737         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6738         if (textureflags & TEXF_ALPHA)
6739         {
6740                 for (i = 3;i < width * height * 4;i += 4)
6741                 {
6742                         if (skindata[i] < 255)
6743                         {
6744                                 skinframe->hasalpha = true;
6745                                 break;
6746                         }
6747                 }
6748                 if (r_loadfog && skinframe->hasalpha)
6749                 {
6750                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6751                         memcpy(fogpixels, skindata, width * height * 4);
6752                         for (i = 0;i < width * height * 4;i += 4)
6753                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6754                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6755                         Mem_Free(fogpixels);
6756                 }
6757         }
6758
6759         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6760         //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]);
6761
6762         return skinframe;
6763 }
6764
6765 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6766 {
6767         int i;
6768         int featuresmask;
6769         skinframe_t *skinframe;
6770
6771         if (cls.state == ca_dedicated)
6772                 return NULL;
6773
6774         // if already loaded just return it, otherwise make a new skinframe
6775         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6776         if (skinframe && skinframe->base)
6777                 return skinframe;
6778
6779         skinframe->stain = NULL;
6780         skinframe->merged = NULL;
6781         skinframe->base = NULL;
6782         skinframe->pants = NULL;
6783         skinframe->shirt = NULL;
6784         skinframe->nmap = NULL;
6785         skinframe->gloss = NULL;
6786         skinframe->glow = NULL;
6787         skinframe->fog = NULL;
6788         skinframe->reflect = NULL;
6789         skinframe->hasalpha = false;
6790
6791         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6792         if (!skindata)
6793                 return NULL;
6794
6795         if (developer_loading.integer)
6796                 Con_Printf("loading quake skin \"%s\"\n", name);
6797
6798         // 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)
6799         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6800         memcpy(skinframe->qpixels, skindata, width*height);
6801         skinframe->qwidth = width;
6802         skinframe->qheight = height;
6803
6804         featuresmask = 0;
6805         for (i = 0;i < width * height;i++)
6806                 featuresmask |= palette_featureflags[skindata[i]];
6807
6808         skinframe->hasalpha = false;
6809         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6810         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6811         skinframe->qgeneratemerged = true;
6812         skinframe->qgeneratebase = skinframe->qhascolormapping;
6813         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6814
6815         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6816         //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]);
6817
6818         return skinframe;
6819 }
6820
6821 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6822 {
6823         int width;
6824         int height;
6825         unsigned char *skindata;
6826
6827         if (!skinframe->qpixels)
6828                 return;
6829
6830         if (!skinframe->qhascolormapping)
6831                 colormapped = false;
6832
6833         if (colormapped)
6834         {
6835                 if (!skinframe->qgeneratebase)
6836                         return;
6837         }
6838         else
6839         {
6840                 if (!skinframe->qgeneratemerged)
6841                         return;
6842         }
6843
6844         width = skinframe->qwidth;
6845         height = skinframe->qheight;
6846         skindata = skinframe->qpixels;
6847
6848         if (skinframe->qgeneratenmap)
6849         {
6850                 unsigned char *temp1, *temp2;
6851                 skinframe->qgeneratenmap = false;
6852                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6853                 temp2 = temp1 + width * height * 4;
6854                 // use either a custom palette or the quake palette
6855                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6856                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6857                 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);
6858                 Mem_Free(temp1);
6859         }
6860
6861         if (skinframe->qgenerateglow)
6862         {
6863                 skinframe->qgenerateglow = false;
6864                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6865         }
6866
6867         if (colormapped)
6868         {
6869                 skinframe->qgeneratebase = false;
6870                 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);
6871                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6872                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6873         }
6874         else
6875         {
6876                 skinframe->qgeneratemerged = false;
6877                 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);
6878         }
6879
6880         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6881         {
6882                 Mem_Free(skinframe->qpixels);
6883                 skinframe->qpixels = NULL;
6884         }
6885 }
6886
6887 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)
6888 {
6889         int i;
6890         skinframe_t *skinframe;
6891
6892         if (cls.state == ca_dedicated)
6893                 return NULL;
6894
6895         // if already loaded just return it, otherwise make a new skinframe
6896         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6897         if (skinframe && skinframe->base)
6898                 return skinframe;
6899
6900         skinframe->stain = NULL;
6901         skinframe->merged = NULL;
6902         skinframe->base = NULL;
6903         skinframe->pants = NULL;
6904         skinframe->shirt = NULL;
6905         skinframe->nmap = NULL;
6906         skinframe->gloss = NULL;
6907         skinframe->glow = NULL;
6908         skinframe->fog = NULL;
6909         skinframe->reflect = NULL;
6910         skinframe->hasalpha = false;
6911
6912         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6913         if (!skindata)
6914                 return NULL;
6915
6916         if (developer_loading.integer)
6917                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6918
6919         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6920         if (textureflags & TEXF_ALPHA)
6921         {
6922                 for (i = 0;i < width * height;i++)
6923                 {
6924                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6925                         {
6926                                 skinframe->hasalpha = true;
6927                                 break;
6928                         }
6929                 }
6930                 if (r_loadfog && skinframe->hasalpha)
6931                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6932         }
6933
6934         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6935         //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]);
6936
6937         return skinframe;
6938 }
6939
6940 skinframe_t *R_SkinFrame_LoadMissing(void)
6941 {
6942         skinframe_t *skinframe;
6943
6944         if (cls.state == ca_dedicated)
6945                 return NULL;
6946
6947         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6948         skinframe->stain = NULL;
6949         skinframe->merged = NULL;
6950         skinframe->base = NULL;
6951         skinframe->pants = NULL;
6952         skinframe->shirt = NULL;
6953         skinframe->nmap = NULL;
6954         skinframe->gloss = NULL;
6955         skinframe->glow = NULL;
6956         skinframe->fog = NULL;
6957         skinframe->reflect = NULL;
6958         skinframe->hasalpha = false;
6959
6960         skinframe->avgcolor[0] = rand() / RAND_MAX;
6961         skinframe->avgcolor[1] = rand() / RAND_MAX;
6962         skinframe->avgcolor[2] = rand() / RAND_MAX;
6963         skinframe->avgcolor[3] = 1;
6964
6965         return skinframe;
6966 }
6967
6968 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6969 typedef struct suffixinfo_s
6970 {
6971         char *suffix;
6972         qboolean flipx, flipy, flipdiagonal;
6973 }
6974 suffixinfo_t;
6975 static suffixinfo_t suffix[3][6] =
6976 {
6977         {
6978                 {"px",   false, false, false},
6979                 {"nx",   false, false, false},
6980                 {"py",   false, false, false},
6981                 {"ny",   false, false, false},
6982                 {"pz",   false, false, false},
6983                 {"nz",   false, false, false}
6984         },
6985         {
6986                 {"posx", false, false, false},
6987                 {"negx", false, false, false},
6988                 {"posy", false, false, false},
6989                 {"negy", false, false, false},
6990                 {"posz", false, false, false},
6991                 {"negz", false, false, false}
6992         },
6993         {
6994                 {"rt",    true, false,  true},
6995                 {"lf",   false,  true,  true},
6996                 {"ft",    true,  true, false},
6997                 {"bk",   false, false, false},
6998                 {"up",    true, false,  true},
6999                 {"dn",    true, false,  true}
7000         }
7001 };
7002
7003 static int componentorder[4] = {0, 1, 2, 3};
7004
7005 rtexture_t *R_LoadCubemap(const char *basename)
7006 {
7007         int i, j, cubemapsize;
7008         unsigned char *cubemappixels, *image_buffer;
7009         rtexture_t *cubemaptexture;
7010         char name[256];
7011         // must start 0 so the first loadimagepixels has no requested width/height
7012         cubemapsize = 0;
7013         cubemappixels = NULL;
7014         cubemaptexture = NULL;
7015         // keep trying different suffix groups (posx, px, rt) until one loads
7016         for (j = 0;j < 3 && !cubemappixels;j++)
7017         {
7018                 // load the 6 images in the suffix group
7019                 for (i = 0;i < 6;i++)
7020                 {
7021                         // generate an image name based on the base and and suffix
7022                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7023                         // load it
7024                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7025                         {
7026                                 // an image loaded, make sure width and height are equal
7027                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7028                                 {
7029                                         // if this is the first image to load successfully, allocate the cubemap memory
7030                                         if (!cubemappixels && image_width >= 1)
7031                                         {
7032                                                 cubemapsize = image_width;
7033                                                 // note this clears to black, so unavailable sides are black
7034                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7035                                         }
7036                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7037                                         if (cubemappixels)
7038                                                 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);
7039                                 }
7040                                 else
7041                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7042                                 // free the image
7043                                 Mem_Free(image_buffer);
7044                         }
7045                 }
7046         }
7047         // if a cubemap loaded, upload it
7048         if (cubemappixels)
7049         {
7050                 if (developer_loading.integer)
7051                         Con_Printf("loading cubemap \"%s\"\n", basename);
7052
7053                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7054                 Mem_Free(cubemappixels);
7055         }
7056         else
7057         {
7058                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7059                 if (developer_loading.integer)
7060                 {
7061                         Con_Printf("(tried tried images ");
7062                         for (j = 0;j < 3;j++)
7063                                 for (i = 0;i < 6;i++)
7064                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7065                         Con_Print(" and was unable to find any of them).\n");
7066                 }
7067         }
7068         return cubemaptexture;
7069 }
7070
7071 rtexture_t *R_GetCubemap(const char *basename)
7072 {
7073         int i;
7074         for (i = 0;i < r_texture_numcubemaps;i++)
7075                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7076                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7077         if (i >= MAX_CUBEMAPS)
7078                 return r_texture_whitecube;
7079         r_texture_numcubemaps++;
7080         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7081         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7082         return r_texture_cubemaps[i].texture;
7083 }
7084
7085 void R_FreeCubemaps(void)
7086 {
7087         int i;
7088         for (i = 0;i < r_texture_numcubemaps;i++)
7089         {
7090                 if (developer_loading.integer)
7091                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7092                 if (r_texture_cubemaps[i].texture)
7093                         R_FreeTexture(r_texture_cubemaps[i].texture);
7094         }
7095         r_texture_numcubemaps = 0;
7096 }
7097
7098 void R_Main_FreeViewCache(void)
7099 {
7100         if (r_refdef.viewcache.entityvisible)
7101                 Mem_Free(r_refdef.viewcache.entityvisible);
7102         if (r_refdef.viewcache.world_pvsbits)
7103                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7104         if (r_refdef.viewcache.world_leafvisible)
7105                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7106         if (r_refdef.viewcache.world_surfacevisible)
7107                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7108         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7109 }
7110
7111 void R_Main_ResizeViewCache(void)
7112 {
7113         int numentities = r_refdef.scene.numentities;
7114         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7115         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7116         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7117         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7118         if (r_refdef.viewcache.maxentities < numentities)
7119         {
7120                 r_refdef.viewcache.maxentities = numentities;
7121                 if (r_refdef.viewcache.entityvisible)
7122                         Mem_Free(r_refdef.viewcache.entityvisible);
7123                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7124         }
7125         if (r_refdef.viewcache.world_numclusters != numclusters)
7126         {
7127                 r_refdef.viewcache.world_numclusters = numclusters;
7128                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7129                 if (r_refdef.viewcache.world_pvsbits)
7130                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7131                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7132         }
7133         if (r_refdef.viewcache.world_numleafs != numleafs)
7134         {
7135                 r_refdef.viewcache.world_numleafs = numleafs;
7136                 if (r_refdef.viewcache.world_leafvisible)
7137                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7138                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7139         }
7140         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7141         {
7142                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7143                 if (r_refdef.viewcache.world_surfacevisible)
7144                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7145                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7146         }
7147 }
7148
7149 extern rtexture_t *loadingscreentexture;
7150 void gl_main_start(void)
7151 {
7152         loadingscreentexture = NULL;
7153         r_texture_blanknormalmap = NULL;
7154         r_texture_white = NULL;
7155         r_texture_grey128 = NULL;
7156         r_texture_black = NULL;
7157         r_texture_whitecube = NULL;
7158         r_texture_normalizationcube = NULL;
7159         r_texture_fogattenuation = NULL;
7160         r_texture_fogheighttexture = NULL;
7161         r_texture_gammaramps = NULL;
7162         r_texture_numcubemaps = 0;
7163
7164         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7165         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7166
7167         switch(vid.renderpath)
7168         {
7169         case RENDERPATH_GL20:
7170         case RENDERPATH_CGGL:
7171         case RENDERPATH_D3D9:
7172         case RENDERPATH_D3D10:
7173         case RENDERPATH_D3D11:
7174                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7175                 Cvar_SetValueQuick(&gl_combine, 1);
7176                 Cvar_SetValueQuick(&r_glsl, 1);
7177                 r_loadnormalmap = true;
7178                 r_loadgloss = true;
7179                 r_loadfog = false;
7180                 break;
7181         case RENDERPATH_GL13:
7182                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7183                 Cvar_SetValueQuick(&gl_combine, 1);
7184                 Cvar_SetValueQuick(&r_glsl, 0);
7185                 r_loadnormalmap = false;
7186                 r_loadgloss = false;
7187                 r_loadfog = true;
7188                 break;
7189         case RENDERPATH_GL11:
7190                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7191                 Cvar_SetValueQuick(&gl_combine, 0);
7192                 Cvar_SetValueQuick(&r_glsl, 0);
7193                 r_loadnormalmap = false;
7194                 r_loadgloss = false;
7195                 r_loadfog = true;
7196                 break;
7197         }
7198
7199         R_AnimCache_Free();
7200         R_FrameData_Reset();
7201
7202         r_numqueries = 0;
7203         r_maxqueries = 0;
7204         memset(r_queries, 0, sizeof(r_queries));
7205
7206         r_qwskincache = NULL;
7207         r_qwskincache_size = 0;
7208
7209         // set up r_skinframe loading system for textures
7210         memset(&r_skinframe, 0, sizeof(r_skinframe));
7211         r_skinframe.loadsequence = 1;
7212         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7213
7214         r_main_texturepool = R_AllocTexturePool();
7215         R_BuildBlankTextures();
7216         R_BuildNoTexture();
7217         if (vid.support.arb_texture_cube_map)
7218         {
7219                 R_BuildWhiteCube();
7220                 R_BuildNormalizationCube();
7221         }
7222         r_texture_fogattenuation = NULL;
7223         r_texture_fogheighttexture = NULL;
7224         r_texture_gammaramps = NULL;
7225         //r_texture_fogintensity = NULL;
7226         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7227         memset(&r_waterstate, 0, sizeof(r_waterstate));
7228         r_glsl_permutation = NULL;
7229         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7230         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7231         glslshaderstring = NULL;
7232 #ifdef SUPPORTCG
7233         r_cg_permutation = NULL;
7234         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7235         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7236         cgshaderstring = NULL;
7237 #endif
7238 #ifdef SUPPORTD3D
7239         r_hlsl_permutation = NULL;
7240         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7241         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7242         hlslshaderstring = NULL;
7243 #endif
7244         memset(&r_svbsp, 0, sizeof (r_svbsp));
7245
7246         r_refdef.fogmasktable_density = 0;
7247 }
7248
7249 void gl_main_shutdown(void)
7250 {
7251         R_AnimCache_Free();
7252         R_FrameData_Reset();
7253
7254         R_Main_FreeViewCache();
7255
7256         switch(vid.renderpath)
7257         {
7258         case RENDERPATH_GL11:
7259         case RENDERPATH_GL13:
7260         case RENDERPATH_GL20:
7261         case RENDERPATH_CGGL:
7262                 if (r_maxqueries)
7263                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7264                 break;
7265         case RENDERPATH_D3D9:
7266                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7267                 break;
7268         case RENDERPATH_D3D10:
7269                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7270                 break;
7271         case RENDERPATH_D3D11:
7272                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7273                 break;
7274         }
7275
7276         r_numqueries = 0;
7277         r_maxqueries = 0;
7278         memset(r_queries, 0, sizeof(r_queries));
7279
7280         r_qwskincache = NULL;
7281         r_qwskincache_size = 0;
7282
7283         // clear out the r_skinframe state
7284         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7285         memset(&r_skinframe, 0, sizeof(r_skinframe));
7286
7287         if (r_svbsp.nodes)
7288                 Mem_Free(r_svbsp.nodes);
7289         memset(&r_svbsp, 0, sizeof (r_svbsp));
7290         R_FreeTexturePool(&r_main_texturepool);
7291         loadingscreentexture = NULL;
7292         r_texture_blanknormalmap = NULL;
7293         r_texture_white = NULL;
7294         r_texture_grey128 = NULL;
7295         r_texture_black = NULL;
7296         r_texture_whitecube = NULL;
7297         r_texture_normalizationcube = NULL;
7298         r_texture_fogattenuation = NULL;
7299         r_texture_fogheighttexture = NULL;
7300         r_texture_gammaramps = NULL;
7301         r_texture_numcubemaps = 0;
7302         //r_texture_fogintensity = NULL;
7303         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7304         memset(&r_waterstate, 0, sizeof(r_waterstate));
7305         R_GLSL_Restart_f();
7306 }
7307
7308 extern void CL_ParseEntityLump(char *entitystring);
7309 void gl_main_newmap(void)
7310 {
7311         // FIXME: move this code to client
7312         char *entities, entname[MAX_QPATH];
7313         if (r_qwskincache)
7314                 Mem_Free(r_qwskincache);
7315         r_qwskincache = NULL;
7316         r_qwskincache_size = 0;
7317         if (cl.worldmodel)
7318         {
7319                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7320                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7321                 {
7322                         CL_ParseEntityLump(entities);
7323                         Mem_Free(entities);
7324                         return;
7325                 }
7326                 if (cl.worldmodel->brush.entities)
7327                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7328         }
7329         R_Main_FreeViewCache();
7330
7331         R_FrameData_Reset();
7332 }
7333
7334 void GL_Main_Init(void)
7335 {
7336         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7337
7338         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7339         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7340         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7341         if (gamemode == GAME_NEHAHRA)
7342         {
7343                 Cvar_RegisterVariable (&gl_fogenable);
7344                 Cvar_RegisterVariable (&gl_fogdensity);
7345                 Cvar_RegisterVariable (&gl_fogred);
7346                 Cvar_RegisterVariable (&gl_foggreen);
7347                 Cvar_RegisterVariable (&gl_fogblue);
7348                 Cvar_RegisterVariable (&gl_fogstart);
7349                 Cvar_RegisterVariable (&gl_fogend);
7350                 Cvar_RegisterVariable (&gl_skyclip);
7351         }
7352         Cvar_RegisterVariable(&r_motionblur);
7353         Cvar_RegisterVariable(&r_motionblur_maxblur);
7354         Cvar_RegisterVariable(&r_motionblur_bmin);
7355         Cvar_RegisterVariable(&r_motionblur_vmin);
7356         Cvar_RegisterVariable(&r_motionblur_vmax);
7357         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7358         Cvar_RegisterVariable(&r_motionblur_randomize);
7359         Cvar_RegisterVariable(&r_damageblur);
7360         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7361         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7362         Cvar_RegisterVariable(&r_equalize_entities_by);
7363         Cvar_RegisterVariable(&r_equalize_entities_to);
7364         Cvar_RegisterVariable(&r_depthfirst);
7365         Cvar_RegisterVariable(&r_useinfinitefarclip);
7366         Cvar_RegisterVariable(&r_farclip_base);
7367         Cvar_RegisterVariable(&r_farclip_world);
7368         Cvar_RegisterVariable(&r_nearclip);
7369         Cvar_RegisterVariable(&r_showbboxes);
7370         Cvar_RegisterVariable(&r_showsurfaces);
7371         Cvar_RegisterVariable(&r_showtris);
7372         Cvar_RegisterVariable(&r_shownormals);
7373         Cvar_RegisterVariable(&r_showlighting);
7374         Cvar_RegisterVariable(&r_showshadowvolumes);
7375         Cvar_RegisterVariable(&r_showcollisionbrushes);
7376         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7377         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7378         Cvar_RegisterVariable(&r_showdisabledepthtest);
7379         Cvar_RegisterVariable(&r_drawportals);
7380         Cvar_RegisterVariable(&r_drawentities);
7381         Cvar_RegisterVariable(&r_draw2d);
7382         Cvar_RegisterVariable(&r_drawworld);
7383         Cvar_RegisterVariable(&r_cullentities_trace);
7384         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7385         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7386         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7387         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7388         Cvar_RegisterVariable(&r_drawviewmodel);
7389         Cvar_RegisterVariable(&r_drawexteriormodel);
7390         Cvar_RegisterVariable(&r_speeds);
7391         Cvar_RegisterVariable(&r_fullbrights);
7392         Cvar_RegisterVariable(&r_wateralpha);
7393         Cvar_RegisterVariable(&r_dynamic);
7394         Cvar_RegisterVariable(&r_fullbright);
7395         Cvar_RegisterVariable(&r_shadows);
7396         Cvar_RegisterVariable(&r_shadows_darken);
7397         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7398         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7399         Cvar_RegisterVariable(&r_shadows_throwdistance);
7400         Cvar_RegisterVariable(&r_shadows_throwdirection);
7401         Cvar_RegisterVariable(&r_shadows_focus);
7402         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7403         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7404         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7405         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7406         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7407         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7408         Cvar_RegisterVariable(&r_fog_exp2);
7409         Cvar_RegisterVariable(&r_drawfog);
7410         Cvar_RegisterVariable(&r_transparentdepthmasking);
7411         Cvar_RegisterVariable(&r_texture_dds_load);
7412         Cvar_RegisterVariable(&r_texture_dds_save);
7413         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7414         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7415         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7416         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7417         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7418         Cvar_RegisterVariable(&r_textureunits);
7419         Cvar_RegisterVariable(&gl_combine);
7420         Cvar_RegisterVariable(&r_glsl);
7421         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7422         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7423         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7424         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7425         Cvar_RegisterVariable(&r_glsl_postprocess);
7426         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7427         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7428         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7429         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7430         Cvar_RegisterVariable(&r_water);
7431         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7432         Cvar_RegisterVariable(&r_water_clippingplanebias);
7433         Cvar_RegisterVariable(&r_water_refractdistort);
7434         Cvar_RegisterVariable(&r_water_reflectdistort);
7435         Cvar_RegisterVariable(&r_lerpsprites);
7436         Cvar_RegisterVariable(&r_lerpmodels);
7437         Cvar_RegisterVariable(&r_lerplightstyles);
7438         Cvar_RegisterVariable(&r_waterscroll);
7439         Cvar_RegisterVariable(&r_bloom);
7440         Cvar_RegisterVariable(&r_bloom_colorscale);
7441         Cvar_RegisterVariable(&r_bloom_brighten);
7442         Cvar_RegisterVariable(&r_bloom_blur);
7443         Cvar_RegisterVariable(&r_bloom_resolution);
7444         Cvar_RegisterVariable(&r_bloom_colorexponent);
7445         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7446         Cvar_RegisterVariable(&r_hdr);
7447         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7448         Cvar_RegisterVariable(&r_hdr_glowintensity);
7449         Cvar_RegisterVariable(&r_hdr_range);
7450         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7451         Cvar_RegisterVariable(&developer_texturelogging);
7452         Cvar_RegisterVariable(&gl_lightmaps);
7453         Cvar_RegisterVariable(&r_test);
7454         Cvar_RegisterVariable(&r_glsl_saturation);
7455         Cvar_RegisterVariable(&r_framedatasize);
7456         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7457                 Cvar_SetValue("r_fullbrights", 0);
7458         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7459
7460         Cvar_RegisterVariable(&r_track_sprites);
7461         Cvar_RegisterVariable(&r_track_sprites_flags);
7462         Cvar_RegisterVariable(&r_track_sprites_scalew);
7463         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7464         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7465         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7466 }
7467
7468 extern void R_Textures_Init(void);
7469 extern void GL_Draw_Init(void);
7470 extern void GL_Main_Init(void);
7471 extern void R_Shadow_Init(void);
7472 extern void R_Sky_Init(void);
7473 extern void GL_Surf_Init(void);
7474 extern void R_Particles_Init(void);
7475 extern void R_Explosion_Init(void);
7476 extern void gl_backend_init(void);
7477 extern void Sbar_Init(void);
7478 extern void R_LightningBeams_Init(void);
7479 extern void Mod_RenderInit(void);
7480 extern void Font_Init(void);
7481
7482 void Render_Init(void)
7483 {
7484         gl_backend_init();
7485         R_Textures_Init();
7486         GL_Main_Init();
7487         Font_Init();
7488         GL_Draw_Init();
7489         R_Shadow_Init();
7490         R_Sky_Init();
7491         GL_Surf_Init();
7492         Sbar_Init();
7493         R_Particles_Init();
7494         R_Explosion_Init();
7495         R_LightningBeams_Init();
7496         Mod_RenderInit();
7497 }
7498
7499 /*
7500 ===============
7501 GL_Init
7502 ===============
7503 */
7504 extern char *ENGINE_EXTENSIONS;
7505 void GL_Init (void)
7506 {
7507         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7508         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7509         gl_version = (const char *)qglGetString(GL_VERSION);
7510         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7511
7512         if (!gl_extensions)
7513                 gl_extensions = "";
7514         if (!gl_platformextensions)
7515                 gl_platformextensions = "";
7516
7517         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7518         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7519         Con_Printf("GL_VERSION: %s\n", gl_version);
7520         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7521         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7522
7523         VID_CheckExtensions();
7524
7525         // LordHavoc: report supported extensions
7526         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7527
7528         // clear to black (loading plaque will be seen over this)
7529         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7530 }
7531
7532 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7533 {
7534         int i;
7535         mplane_t *p;
7536         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7537         {
7538                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7539                 if (i == 4)
7540                         continue;
7541                 p = r_refdef.view.frustum + i;
7542                 switch(p->signbits)
7543                 {
7544                 default:
7545                 case 0:
7546                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7547                                 return true;
7548                         break;
7549                 case 1:
7550                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7551                                 return true;
7552                         break;
7553                 case 2:
7554                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7555                                 return true;
7556                         break;
7557                 case 3:
7558                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7559                                 return true;
7560                         break;
7561                 case 4:
7562                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7563                                 return true;
7564                         break;
7565                 case 5:
7566                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7567                                 return true;
7568                         break;
7569                 case 6:
7570                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7571                                 return true;
7572                         break;
7573                 case 7:
7574                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7575                                 return true;
7576                         break;
7577                 }
7578         }
7579         return false;
7580 }
7581
7582 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7583 {
7584         int i;
7585         const mplane_t *p;
7586         for (i = 0;i < numplanes;i++)
7587         {
7588                 p = planes + i;
7589                 switch(p->signbits)
7590                 {
7591                 default:
7592                 case 0:
7593                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 1:
7597                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 2:
7601                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 3:
7605                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 4:
7609                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 case 5:
7613                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7614                                 return true;
7615                         break;
7616                 case 6:
7617                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7618                                 return true;
7619                         break;
7620                 case 7:
7621                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7622                                 return true;
7623                         break;
7624                 }
7625         }
7626         return false;
7627 }
7628
7629 //==================================================================================
7630
7631 // LordHavoc: this stores temporary data used within the same frame
7632
7633 qboolean r_framedata_failed;
7634 static size_t r_framedata_size;
7635 static size_t r_framedata_current;
7636 static void *r_framedata_base;
7637
7638 void R_FrameData_Reset(void)
7639 {
7640         if (r_framedata_base)
7641                 Mem_Free(r_framedata_base);
7642         r_framedata_base = NULL;
7643         r_framedata_size = 0;
7644         r_framedata_current = 0;
7645         r_framedata_failed = false;
7646 }
7647
7648 void R_FrameData_NewFrame(void)
7649 {
7650         size_t wantedsize;
7651         if (r_framedata_failed)
7652                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7653         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7654         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7655         if (r_framedata_size != wantedsize)
7656         {
7657                 r_framedata_size = wantedsize;
7658                 if (r_framedata_base)
7659                         Mem_Free(r_framedata_base);
7660                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7661         }
7662         r_framedata_current = 0;
7663         r_framedata_failed = false;
7664 }
7665
7666 void *R_FrameData_Alloc(size_t size)
7667 {
7668         void *data;
7669
7670         // align to 16 byte boundary
7671         size = (size + 15) & ~15;
7672         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7673         r_framedata_current += size;
7674
7675         // check overflow
7676         if (r_framedata_current > r_framedata_size)
7677                 r_framedata_failed = true;
7678
7679         // return NULL on everything after a failure
7680         if (r_framedata_failed)
7681                 return NULL;
7682
7683         return data;
7684 }
7685
7686 void *R_FrameData_Store(size_t size, void *data)
7687 {
7688         void *d = R_FrameData_Alloc(size);
7689         if (d)
7690                 memcpy(d, data, size);
7691         return d;
7692 }
7693
7694 //==================================================================================
7695
7696 // LordHavoc: animcache originally written by Echon, rewritten since then
7697
7698 /**
7699  * Animation cache prevents re-generating mesh data for an animated model
7700  * multiple times in one frame for lighting, shadowing, reflections, etc.
7701  */
7702
7703 void R_AnimCache_Free(void)
7704 {
7705 }
7706
7707 void R_AnimCache_ClearCache(void)
7708 {
7709         int i;
7710         entity_render_t *ent;
7711
7712         for (i = 0;i < r_refdef.scene.numentities;i++)
7713         {
7714                 ent = r_refdef.scene.entities[i];
7715                 ent->animcache_vertex3f = NULL;
7716                 ent->animcache_normal3f = NULL;
7717                 ent->animcache_svector3f = NULL;
7718                 ent->animcache_tvector3f = NULL;
7719                 ent->animcache_vertexposition = NULL;
7720                 ent->animcache_vertexmesh = NULL;
7721                 ent->animcache_vertexpositionbuffer = NULL;
7722                 ent->animcache_vertexmeshbuffer = NULL;
7723         }
7724 }
7725
7726 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7727 {
7728         int i;
7729         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7730                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7731         if (!ent->animcache_vertexposition)
7732                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7733         if (ent->animcache_vertexposition)
7734         {
7735                 for (i = 0;i < numvertices;i++)
7736                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
7737                 // TODO: upload vertex buffer?
7738         }
7739         if (ent->animcache_vertexmesh)
7740         {
7741                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7742                 for (i = 0;i < numvertices;i++)
7743                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
7744                 if (ent->animcache_svector3f)
7745                         for (i = 0;i < numvertices;i++)
7746                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
7747                 if (ent->animcache_tvector3f)
7748                         for (i = 0;i < numvertices;i++)
7749                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
7750                 if (ent->animcache_normal3f)
7751                         for (i = 0;i < numvertices;i++)
7752                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
7753                 // TODO: upload vertex buffer?
7754         }
7755 }
7756
7757 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7758 {
7759         dp_model_t *model = ent->model;
7760         int numvertices;
7761         // see if it's already cached this frame
7762         if (ent->animcache_vertex3f)
7763         {
7764                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7765                 if (wantnormals || wanttangents)
7766                 {
7767                         if (ent->animcache_normal3f)
7768                                 wantnormals = false;
7769                         if (ent->animcache_svector3f)
7770                                 wanttangents = false;
7771                         if (wantnormals || wanttangents)
7772                         {
7773                                 numvertices = model->surfmesh.num_vertices;
7774                                 if (wantnormals)
7775                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7776                                 if (wanttangents)
7777                                 {
7778                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7779                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7780                                 }
7781                                 if (!r_framedata_failed)
7782                                 {
7783                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7784                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7785                                 }
7786                         }
7787                 }
7788         }
7789         else
7790         {
7791                 // see if this ent is worth caching
7792                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7793                         return false;
7794                 // get some memory for this entity and generate mesh data
7795                 numvertices = model->surfmesh.num_vertices;
7796                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7797                 if (wantnormals)
7798                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7799                 if (wanttangents)
7800                 {
7801                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7802                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7803                 }
7804                 if (!r_framedata_failed)
7805                 {
7806                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7807                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7808                 }
7809         }
7810         return !r_framedata_failed;
7811 }
7812
7813 void R_AnimCache_CacheVisibleEntities(void)
7814 {
7815         int i;
7816         qboolean wantnormals = true;
7817         qboolean wanttangents = !r_showsurfaces.integer;
7818
7819         switch(vid.renderpath)
7820         {
7821         case RENDERPATH_GL20:
7822         case RENDERPATH_CGGL:
7823         case RENDERPATH_D3D9:
7824         case RENDERPATH_D3D10:
7825         case RENDERPATH_D3D11:
7826                 break;
7827         case RENDERPATH_GL13:
7828         case RENDERPATH_GL11:
7829                 wanttangents = false;
7830                 break;
7831         }
7832
7833         if (r_shownormals.integer)
7834                 wanttangents = wantnormals = true;
7835
7836         // TODO: thread this
7837         // NOTE: R_PrepareRTLights() also caches entities
7838
7839         for (i = 0;i < r_refdef.scene.numentities;i++)
7840                 if (r_refdef.viewcache.entityvisible[i])
7841                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7842 }
7843
7844 //==================================================================================
7845
7846 static void R_View_UpdateEntityLighting (void)
7847 {
7848         int i;
7849         entity_render_t *ent;
7850         vec3_t tempdiffusenormal, avg;
7851         vec_t f, fa, fd, fdd;
7852         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7853
7854         for (i = 0;i < r_refdef.scene.numentities;i++)
7855         {
7856                 ent = r_refdef.scene.entities[i];
7857
7858                 // skip unseen models
7859                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7860                         continue;
7861
7862                 // skip bsp models
7863                 if (ent->model && ent->model->brush.num_leafs)
7864                 {
7865                         // TODO: use modellight for r_ambient settings on world?
7866                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7867                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7868                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7869                         continue;
7870                 }
7871
7872                 // fetch the lighting from the worldmodel data
7873                 VectorClear(ent->modellight_ambient);
7874                 VectorClear(ent->modellight_diffuse);
7875                 VectorClear(tempdiffusenormal);
7876                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7877                 {
7878                         vec3_t org;
7879                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7880                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7881                         if(ent->flags & RENDER_EQUALIZE)
7882                         {
7883                                 // first fix up ambient lighting...
7884                                 if(r_equalize_entities_minambient.value > 0)
7885                                 {
7886                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7887                                         if(fd > 0)
7888                                         {
7889                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7890                                                 if(fa < r_equalize_entities_minambient.value * fd)
7891                                                 {
7892                                                         // solve:
7893                                                         //   fa'/fd' = minambient
7894                                                         //   fa'+0.25*fd' = fa+0.25*fd
7895                                                         //   ...
7896                                                         //   fa' = fd' * minambient
7897                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7898                                                         //   ...
7899                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7900                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7901                                                         //   ...
7902                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7903                                                         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
7904                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7905                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7906                                                 }
7907                                         }
7908                                 }
7909
7910                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7911                                 {
7912                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7913                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7914                                         if(f > 0)
7915                                         {
7916                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7917                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7918                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7919                                         }
7920                                 }
7921                         }
7922                 }
7923                 else // highly rare
7924                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7925
7926                 // move the light direction into modelspace coordinates for lighting code
7927                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7928                 if(VectorLength2(ent->modellight_lightdir) == 0)
7929                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7930                 VectorNormalize(ent->modellight_lightdir);
7931         }
7932 }
7933
7934 #define MAX_LINEOFSIGHTTRACES 64
7935
7936 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7937 {
7938         int i;
7939         vec3_t boxmins, boxmaxs;
7940         vec3_t start;
7941         vec3_t end;
7942         dp_model_t *model = r_refdef.scene.worldmodel;
7943
7944         if (!model || !model->brush.TraceLineOfSight)
7945                 return true;
7946
7947         // expand the box a little
7948         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7949         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7950         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7951         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7952         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7953         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7954
7955         // return true if eye is inside enlarged box
7956         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7957                 return true;
7958
7959         // try center
7960         VectorCopy(eye, start);
7961         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7962         if (model->brush.TraceLineOfSight(model, start, end))
7963                 return true;
7964
7965         // try various random positions
7966         for (i = 0;i < numsamples;i++)
7967         {
7968                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7969                 if (model->brush.TraceLineOfSight(model, start, end))
7970                         return true;
7971         }
7972
7973         return false;
7974 }
7975
7976
7977 static void R_View_UpdateEntityVisible (void)
7978 {
7979         int i;
7980         int renderimask;
7981         int samples;
7982         entity_render_t *ent;
7983
7984         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7985                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7986                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7987                 :                                                          RENDER_EXTERIORMODEL;
7988         if (!r_drawviewmodel.integer)
7989                 renderimask |= RENDER_VIEWMODEL;
7990         if (!r_drawexteriormodel.integer)
7991                 renderimask |= RENDER_EXTERIORMODEL;
7992         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7993         {
7994                 // worldmodel can check visibility
7995                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7996                 for (i = 0;i < r_refdef.scene.numentities;i++)
7997                 {
7998                         ent = r_refdef.scene.entities[i];
7999                         if (!(ent->flags & renderimask))
8000                         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)))
8001                         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))
8002                                 r_refdef.viewcache.entityvisible[i] = true;
8003                 }
8004                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8005                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8006                 {
8007                         for (i = 0;i < r_refdef.scene.numentities;i++)
8008                         {
8009                                 ent = r_refdef.scene.entities[i];
8010                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8011                                 {
8012                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8013                                         if (samples < 0)
8014                                                 continue; // temp entities do pvs only
8015                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8016                                                 ent->last_trace_visibility = realtime;
8017                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8018                                                 r_refdef.viewcache.entityvisible[i] = 0;
8019                                 }
8020                         }
8021                 }
8022         }
8023         else
8024         {
8025                 // no worldmodel or it can't check visibility
8026                 for (i = 0;i < r_refdef.scene.numentities;i++)
8027                 {
8028                         ent = r_refdef.scene.entities[i];
8029                         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));
8030                 }
8031         }
8032 }
8033
8034 /// only used if skyrendermasked, and normally returns false
8035 int R_DrawBrushModelsSky (void)
8036 {
8037         int i, sky;
8038         entity_render_t *ent;
8039
8040         sky = false;
8041         for (i = 0;i < r_refdef.scene.numentities;i++)
8042         {
8043                 if (!r_refdef.viewcache.entityvisible[i])
8044                         continue;
8045                 ent = r_refdef.scene.entities[i];
8046                 if (!ent->model || !ent->model->DrawSky)
8047                         continue;
8048                 ent->model->DrawSky(ent);
8049                 sky = true;
8050         }
8051         return sky;
8052 }
8053
8054 static void R_DrawNoModel(entity_render_t *ent);
8055 static void R_DrawModels(void)
8056 {
8057         int i;
8058         entity_render_t *ent;
8059
8060         for (i = 0;i < r_refdef.scene.numentities;i++)
8061         {
8062                 if (!r_refdef.viewcache.entityvisible[i])
8063                         continue;
8064                 ent = r_refdef.scene.entities[i];
8065                 r_refdef.stats.entities++;
8066                 if (ent->model && ent->model->Draw != NULL)
8067                         ent->model->Draw(ent);
8068                 else
8069                         R_DrawNoModel(ent);
8070         }
8071 }
8072
8073 static void R_DrawModelsDepth(void)
8074 {
8075         int i;
8076         entity_render_t *ent;
8077
8078         for (i = 0;i < r_refdef.scene.numentities;i++)
8079         {
8080                 if (!r_refdef.viewcache.entityvisible[i])
8081                         continue;
8082                 ent = r_refdef.scene.entities[i];
8083                 if (ent->model && ent->model->DrawDepth != NULL)
8084                         ent->model->DrawDepth(ent);
8085         }
8086 }
8087
8088 static void R_DrawModelsDebug(void)
8089 {
8090         int i;
8091         entity_render_t *ent;
8092
8093         for (i = 0;i < r_refdef.scene.numentities;i++)
8094         {
8095                 if (!r_refdef.viewcache.entityvisible[i])
8096                         continue;
8097                 ent = r_refdef.scene.entities[i];
8098                 if (ent->model && ent->model->DrawDebug != NULL)
8099                         ent->model->DrawDebug(ent);
8100         }
8101 }
8102
8103 static void R_DrawModelsAddWaterPlanes(void)
8104 {
8105         int i;
8106         entity_render_t *ent;
8107
8108         for (i = 0;i < r_refdef.scene.numentities;i++)
8109         {
8110                 if (!r_refdef.viewcache.entityvisible[i])
8111                         continue;
8112                 ent = r_refdef.scene.entities[i];
8113                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8114                         ent->model->DrawAddWaterPlanes(ent);
8115         }
8116 }
8117
8118 static void R_View_SetFrustum(void)
8119 {
8120         int i;
8121         double slopex, slopey;
8122         vec3_t forward, left, up, origin;
8123
8124         // we can't trust r_refdef.view.forward and friends in reflected scenes
8125         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8126
8127 #if 0
8128         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8129         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8130         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8131         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8132         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8133         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8134         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8135         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8136         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8137         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8138         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8139         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8140 #endif
8141
8142 #if 0
8143         zNear = r_refdef.nearclip;
8144         nudge = 1.0 - 1.0 / (1<<23);
8145         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8146         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8147         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8148         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8149         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8150         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8151         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8152         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8153 #endif
8154
8155
8156
8157 #if 0
8158         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8159         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8160         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8161         r_refdef.view.frustum[0].dist = m[15] - m[12];
8162
8163         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8164         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8165         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8166         r_refdef.view.frustum[1].dist = m[15] + m[12];
8167
8168         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8169         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8170         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8171         r_refdef.view.frustum[2].dist = m[15] - m[13];
8172
8173         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8174         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8175         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8176         r_refdef.view.frustum[3].dist = m[15] + m[13];
8177
8178         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8179         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8180         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8181         r_refdef.view.frustum[4].dist = m[15] - m[14];
8182
8183         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8184         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8185         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8186         r_refdef.view.frustum[5].dist = m[15] + m[14];
8187 #endif
8188
8189         if (r_refdef.view.useperspective)
8190         {
8191                 slopex = 1.0 / r_refdef.view.frustum_x;
8192                 slopey = 1.0 / r_refdef.view.frustum_y;
8193                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8194                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8195                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8196                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8197                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8198
8199                 // Leaving those out was a mistake, those were in the old code, and they
8200                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8201                 // I couldn't reproduce it after adding those normalizations. --blub
8202                 VectorNormalize(r_refdef.view.frustum[0].normal);
8203                 VectorNormalize(r_refdef.view.frustum[1].normal);
8204                 VectorNormalize(r_refdef.view.frustum[2].normal);
8205                 VectorNormalize(r_refdef.view.frustum[3].normal);
8206
8207                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8208                 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]);
8209                 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]);
8210                 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]);
8211                 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]);
8212
8213                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8214                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8215                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8216                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8217                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8218         }
8219         else
8220         {
8221                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8222                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8223                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8224                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8225                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8226                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8227                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8228                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8229                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8230                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8231         }
8232         r_refdef.view.numfrustumplanes = 5;
8233
8234         if (r_refdef.view.useclipplane)
8235         {
8236                 r_refdef.view.numfrustumplanes = 6;
8237                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8238         }
8239
8240         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8241                 PlaneClassify(r_refdef.view.frustum + i);
8242
8243         // LordHavoc: note to all quake engine coders, Quake had a special case
8244         // for 90 degrees which assumed a square view (wrong), so I removed it,
8245         // Quake2 has it disabled as well.
8246
8247         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8248         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8249         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8250         //PlaneClassify(&frustum[0]);
8251
8252         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8253         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8254         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8255         //PlaneClassify(&frustum[1]);
8256
8257         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8258         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8259         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8260         //PlaneClassify(&frustum[2]);
8261
8262         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8263         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8264         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8265         //PlaneClassify(&frustum[3]);
8266
8267         // nearclip plane
8268         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8269         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8270         //PlaneClassify(&frustum[4]);
8271 }
8272
8273 void R_View_Update(void)
8274 {
8275         R_Main_ResizeViewCache();
8276         R_View_SetFrustum();
8277         R_View_WorldVisibility(r_refdef.view.useclipplane);
8278         R_View_UpdateEntityVisible();
8279         R_View_UpdateEntityLighting();
8280 }
8281
8282 void R_SetupView(qboolean allowwaterclippingplane)
8283 {
8284         const float *customclipplane = NULL;
8285         float plane[4];
8286         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8287         {
8288                 // LordHavoc: couldn't figure out how to make this approach the
8289                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8290                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8291                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8292                         dist = r_refdef.view.clipplane.dist;
8293                 plane[0] = r_refdef.view.clipplane.normal[0];
8294                 plane[1] = r_refdef.view.clipplane.normal[1];
8295                 plane[2] = r_refdef.view.clipplane.normal[2];
8296                 plane[3] = dist;
8297                 customclipplane = plane;
8298         }
8299
8300         if (!r_refdef.view.useperspective)
8301                 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);
8302         else if (vid.stencil && r_useinfinitefarclip.integer)
8303                 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);
8304         else
8305                 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);
8306         R_SetViewport(&r_refdef.view.viewport);
8307 }
8308
8309 void R_EntityMatrix(const matrix4x4_t *matrix)
8310 {
8311         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8312         {
8313                 gl_modelmatrixchanged = false;
8314                 gl_modelmatrix = *matrix;
8315                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8316                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8317                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8318                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8319                 CHECKGLERROR
8320                 switch(vid.renderpath)
8321                 {
8322                 case RENDERPATH_D3D9:
8323 #ifdef SUPPORTD3D
8324                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8325                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8326 #endif
8327                         break;
8328                 case RENDERPATH_D3D10:
8329                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8330                         break;
8331                 case RENDERPATH_D3D11:
8332                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8333                         break;
8334                 case RENDERPATH_GL20:
8335                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8336                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8337                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8338                         break;
8339                 case RENDERPATH_CGGL:
8340 #ifdef SUPPORTCG
8341                         CHECKCGERROR
8342                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8343                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8344                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8345 #endif
8346                         break;
8347                 case RENDERPATH_GL13:
8348                 case RENDERPATH_GL11:
8349                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8350                         break;
8351                 }
8352         }
8353 }
8354
8355 void R_ResetViewRendering2D(void)
8356 {
8357         r_viewport_t viewport;
8358         DrawQ_Finish();
8359
8360         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8361         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);
8362         R_SetViewport(&viewport);
8363         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8364         GL_Color(1, 1, 1, 1);
8365         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8366         GL_BlendFunc(GL_ONE, GL_ZERO);
8367         GL_AlphaTest(false);
8368         GL_ScissorTest(false);
8369         GL_DepthMask(false);
8370         GL_DepthRange(0, 1);
8371         GL_DepthTest(false);
8372         GL_DepthFunc(GL_LEQUAL);
8373         R_EntityMatrix(&identitymatrix);
8374         R_Mesh_ResetTextureState();
8375         GL_PolygonOffset(0, 0);
8376         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8377         switch(vid.renderpath)
8378         {
8379         case RENDERPATH_GL11:
8380         case RENDERPATH_GL13:
8381         case RENDERPATH_GL20:
8382         case RENDERPATH_CGGL:
8383                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8384                 break;
8385         case RENDERPATH_D3D9:
8386         case RENDERPATH_D3D10:
8387         case RENDERPATH_D3D11:
8388                 break;
8389         }
8390         GL_CullFace(GL_NONE);
8391 }
8392
8393 void R_ResetViewRendering3D(void)
8394 {
8395         DrawQ_Finish();
8396
8397         R_SetupView(true);
8398         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8399         GL_Color(1, 1, 1, 1);
8400         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8401         GL_BlendFunc(GL_ONE, GL_ZERO);
8402         GL_AlphaTest(false);
8403         GL_ScissorTest(true);
8404         GL_DepthMask(true);
8405         GL_DepthRange(0, 1);
8406         GL_DepthTest(true);
8407         GL_DepthFunc(GL_LEQUAL);
8408         R_EntityMatrix(&identitymatrix);
8409         R_Mesh_ResetTextureState();
8410         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8411         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8412         switch(vid.renderpath)
8413         {
8414         case RENDERPATH_GL11:
8415         case RENDERPATH_GL13:
8416         case RENDERPATH_GL20:
8417         case RENDERPATH_CGGL:
8418                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8419                 break;
8420         case RENDERPATH_D3D9:
8421         case RENDERPATH_D3D10:
8422         case RENDERPATH_D3D11:
8423                 break;
8424         }
8425         GL_CullFace(r_refdef.view.cullface_back);
8426 }
8427
8428 /*
8429 ================
8430 R_RenderView_UpdateViewVectors
8431 ================
8432 */
8433 static void R_RenderView_UpdateViewVectors(void)
8434 {
8435         // break apart the view matrix into vectors for various purposes
8436         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8437         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8438         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8439         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8440         // make an inverted copy of the view matrix for tracking sprites
8441         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8442 }
8443
8444 void R_RenderScene(void);
8445 void R_RenderWaterPlanes(void);
8446
8447 static void R_Water_StartFrame(void)
8448 {
8449         int i;
8450         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8451         r_waterstate_waterplane_t *p;
8452
8453         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8454                 return;
8455
8456         switch(vid.renderpath)
8457         {
8458         case RENDERPATH_GL20:
8459         case RENDERPATH_CGGL:
8460         case RENDERPATH_D3D9:
8461         case RENDERPATH_D3D10:
8462         case RENDERPATH_D3D11:
8463                 break;
8464         case RENDERPATH_GL13:
8465         case RENDERPATH_GL11:
8466                 return;
8467         }
8468
8469         // set waterwidth and waterheight to the water resolution that will be
8470         // used (often less than the screen resolution for faster rendering)
8471         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8472         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8473
8474         // calculate desired texture sizes
8475         // can't use water if the card does not support the texture size
8476         if (!r_water.integer || r_showsurfaces.integer)
8477                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8478         else if (vid.support.arb_texture_non_power_of_two)
8479         {
8480                 texturewidth = waterwidth;
8481                 textureheight = waterheight;
8482                 camerawidth = waterwidth;
8483                 cameraheight = waterheight;
8484         }
8485         else
8486         {
8487                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8488                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8489                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8490                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8491         }
8492
8493         // allocate textures as needed
8494         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8495         {
8496                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8497                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8498                 {
8499                         if (p->texture_refraction)
8500                                 R_FreeTexture(p->texture_refraction);
8501                         p->texture_refraction = NULL;
8502                         if (p->texture_reflection)
8503                                 R_FreeTexture(p->texture_reflection);
8504                         p->texture_reflection = NULL;
8505                         if (p->texture_camera)
8506                                 R_FreeTexture(p->texture_camera);
8507                         p->texture_camera = NULL;
8508                 }
8509                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8510                 r_waterstate.texturewidth = texturewidth;
8511                 r_waterstate.textureheight = textureheight;
8512                 r_waterstate.camerawidth = camerawidth;
8513                 r_waterstate.cameraheight = cameraheight;
8514         }
8515
8516         if (r_waterstate.texturewidth)
8517         {
8518                 r_waterstate.enabled = true;
8519
8520                 // when doing a reduced render (HDR) we want to use a smaller area
8521                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8522                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8523
8524                 // set up variables that will be used in shader setup
8525                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8526                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8527                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8528                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8529         }
8530
8531         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8532         r_waterstate.numwaterplanes = 0;
8533 }
8534
8535 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8536 {
8537         int triangleindex, planeindex;
8538         const int *e;
8539         vec3_t vert[3];
8540         vec3_t normal;
8541         vec3_t center;
8542         mplane_t plane;
8543         int cam_ent;
8544         r_waterstate_waterplane_t *p;
8545         texture_t *t = R_GetCurrentTexture(surface->texture);
8546         cam_ent = t->camera_entity;
8547         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8548                 cam_ent = 0;
8549
8550         // just use the first triangle with a valid normal for any decisions
8551         VectorClear(normal);
8552         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8553         {
8554                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8555                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8556                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8557                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8558                 if (VectorLength2(normal) >= 0.001)
8559                         break;
8560         }
8561
8562         VectorCopy(normal, plane.normal);
8563         VectorNormalize(plane.normal);
8564         plane.dist = DotProduct(vert[0], plane.normal);
8565         PlaneClassify(&plane);
8566         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8567         {
8568                 // skip backfaces (except if nocullface is set)
8569                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8570                         return;
8571                 VectorNegate(plane.normal, plane.normal);
8572                 plane.dist *= -1;
8573                 PlaneClassify(&plane);
8574         }
8575
8576
8577         // find a matching plane if there is one
8578         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8579                 if(p->camera_entity == t->camera_entity)
8580                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8581                                 break;
8582         if (planeindex >= r_waterstate.maxwaterplanes)
8583                 return; // nothing we can do, out of planes
8584
8585         // if this triangle does not fit any known plane rendered this frame, add one
8586         if (planeindex >= r_waterstate.numwaterplanes)
8587         {
8588                 // store the new plane
8589                 r_waterstate.numwaterplanes++;
8590                 p->plane = plane;
8591                 // clear materialflags and pvs
8592                 p->materialflags = 0;
8593                 p->pvsvalid = false;
8594                 p->camera_entity = t->camera_entity;
8595         }
8596         // merge this surface's materialflags into the waterplane
8597         p->materialflags |= t->currentmaterialflags;
8598         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8599         {
8600                 // merge this surface's PVS into the waterplane
8601                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8602                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8603                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8604                 {
8605                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8606                         p->pvsvalid = true;
8607                 }
8608         }
8609 }
8610
8611 static void R_Water_ProcessPlanes(void)
8612 {
8613         r_refdef_view_t originalview;
8614         r_refdef_view_t myview;
8615         int planeindex;
8616         r_waterstate_waterplane_t *p;
8617         vec3_t visorigin;
8618
8619         originalview = r_refdef.view;
8620
8621         // make sure enough textures are allocated
8622         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8623         {
8624                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8625                 {
8626                         if (!p->texture_refraction)
8627                                 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);
8628                         if (!p->texture_refraction)
8629                                 goto error;
8630                 }
8631                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8632                 {
8633                         if (!p->texture_camera)
8634                                 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);
8635                         if (!p->texture_camera)
8636                                 goto error;
8637                 }
8638
8639                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8640                 {
8641                         if (!p->texture_reflection)
8642                                 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);
8643                         if (!p->texture_reflection)
8644                                 goto error;
8645                 }
8646         }
8647
8648         // render views
8649         r_refdef.view = originalview;
8650         r_refdef.view.showdebug = false;
8651         r_refdef.view.width = r_waterstate.waterwidth;
8652         r_refdef.view.height = r_waterstate.waterheight;
8653         r_refdef.view.useclipplane = true;
8654         myview = r_refdef.view;
8655         r_waterstate.renderingscene = true;
8656         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8657         {
8658                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8659                 {
8660                         r_refdef.view = myview;
8661                         // render reflected scene and copy into texture
8662                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8663                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8664                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8665                         r_refdef.view.clipplane = p->plane;
8666                         // reverse the cullface settings for this render
8667                         r_refdef.view.cullface_front = GL_FRONT;
8668                         r_refdef.view.cullface_back = GL_BACK;
8669                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8670                         {
8671                                 r_refdef.view.usecustompvs = true;
8672                                 if (p->pvsvalid)
8673                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8674                                 else
8675                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8676                         }
8677
8678                         R_ResetViewRendering3D();
8679                         R_ClearScreen(r_refdef.fogenabled);
8680                         R_View_Update();
8681                         R_RenderScene();
8682
8683                         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);
8684                 }
8685
8686                 // render the normal view scene and copy into texture
8687                 // (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)
8688                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8689                 {
8690                         r_waterstate.renderingrefraction = true;
8691                         r_refdef.view = myview;
8692
8693                         r_refdef.view.clipplane = p->plane;
8694                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8695                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8696
8697                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8698                         {
8699                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8700                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8701                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8702                                 R_RenderView_UpdateViewVectors();
8703                                 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);
8704                         }
8705
8706                         PlaneClassify(&r_refdef.view.clipplane);
8707
8708                         R_ResetViewRendering3D();
8709                         R_ClearScreen(r_refdef.fogenabled);
8710                         R_View_Update();
8711                         R_RenderScene();
8712
8713                         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);
8714                         r_waterstate.renderingrefraction = false;
8715                 }
8716                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8717                 {
8718                         r_refdef.view = myview;
8719
8720                         r_refdef.view.clipplane = p->plane;
8721                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8722                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8723
8724                         r_refdef.view.width = r_waterstate.camerawidth;
8725                         r_refdef.view.height = r_waterstate.cameraheight;
8726                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8727                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8728
8729                         if(p->camera_entity)
8730                         {
8731                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8732                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8733                         }
8734
8735                         // reverse the cullface settings for this render
8736                         r_refdef.view.cullface_front = GL_FRONT;
8737                         r_refdef.view.cullface_back = GL_BACK;
8738                         // also reverse the view matrix
8739                         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
8740                         R_RenderView_UpdateViewVectors();
8741                         if(p->camera_entity)
8742                                 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);
8743                         
8744                         // camera needs no clipplane
8745                         r_refdef.view.useclipplane = false;
8746
8747                         PlaneClassify(&r_refdef.view.clipplane);
8748
8749                         R_ResetViewRendering3D();
8750                         R_ClearScreen(r_refdef.fogenabled);
8751                         R_View_Update();
8752                         R_RenderScene();
8753
8754                         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);
8755                         r_waterstate.renderingrefraction = false;
8756                 }
8757
8758         }
8759         r_waterstate.renderingscene = false;
8760         r_refdef.view = originalview;
8761         R_ResetViewRendering3D();
8762         R_ClearScreen(r_refdef.fogenabled);
8763         R_View_Update();
8764         return;
8765 error:
8766         r_refdef.view = originalview;
8767         r_waterstate.renderingscene = false;
8768         Cvar_SetValueQuick(&r_water, 0);
8769         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8770         return;
8771 }
8772
8773 void R_Bloom_StartFrame(void)
8774 {
8775         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8776
8777         switch(vid.renderpath)
8778         {
8779         case RENDERPATH_GL20:
8780         case RENDERPATH_CGGL:
8781         case RENDERPATH_D3D9:
8782         case RENDERPATH_D3D10:
8783         case RENDERPATH_D3D11:
8784                 break;
8785         case RENDERPATH_GL13:
8786         case RENDERPATH_GL11:
8787                 return;
8788         }
8789
8790         // set bloomwidth and bloomheight to the bloom resolution that will be
8791         // used (often less than the screen resolution for faster rendering)
8792         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8793         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8794         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8795         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8796         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8797
8798         // calculate desired texture sizes
8799         if (vid.support.arb_texture_non_power_of_two)
8800         {
8801                 screentexturewidth = r_refdef.view.width;
8802                 screentextureheight = r_refdef.view.height;
8803                 bloomtexturewidth = r_bloomstate.bloomwidth;
8804                 bloomtextureheight = r_bloomstate.bloomheight;
8805         }
8806         else
8807         {
8808                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8809                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8810                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8811                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8812         }
8813
8814         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))
8815         {
8816                 Cvar_SetValueQuick(&r_hdr, 0);
8817                 Cvar_SetValueQuick(&r_bloom, 0);
8818                 Cvar_SetValueQuick(&r_motionblur, 0);
8819                 Cvar_SetValueQuick(&r_damageblur, 0);
8820         }
8821
8822         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)))
8823                 screentexturewidth = screentextureheight = 0;
8824         if (!r_hdr.integer && !r_bloom.integer)
8825                 bloomtexturewidth = bloomtextureheight = 0;
8826
8827         // allocate textures as needed
8828         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8829         {
8830                 if (r_bloomstate.texture_screen)
8831                         R_FreeTexture(r_bloomstate.texture_screen);
8832                 r_bloomstate.texture_screen = NULL;
8833                 r_bloomstate.screentexturewidth = screentexturewidth;
8834                 r_bloomstate.screentextureheight = screentextureheight;
8835                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8836                         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);
8837         }
8838         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8839         {
8840                 if (r_bloomstate.texture_bloom)
8841                         R_FreeTexture(r_bloomstate.texture_bloom);
8842                 r_bloomstate.texture_bloom = NULL;
8843                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8844                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8845                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8846                         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);
8847         }
8848
8849         // when doing a reduced render (HDR) we want to use a smaller area
8850         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8851         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8852         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8853         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8854         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8855
8856         // set up a texcoord array for the full resolution screen image
8857         // (we have to keep this around to copy back during final render)
8858         r_bloomstate.screentexcoord2f[0] = 0;
8859         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8860         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8861         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8862         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8863         r_bloomstate.screentexcoord2f[5] = 0;
8864         r_bloomstate.screentexcoord2f[6] = 0;
8865         r_bloomstate.screentexcoord2f[7] = 0;
8866
8867         // set up a texcoord array for the reduced resolution bloom image
8868         // (which will be additive blended over the screen image)
8869         r_bloomstate.bloomtexcoord2f[0] = 0;
8870         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8871         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8872         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8873         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8874         r_bloomstate.bloomtexcoord2f[5] = 0;
8875         r_bloomstate.bloomtexcoord2f[6] = 0;
8876         r_bloomstate.bloomtexcoord2f[7] = 0;
8877
8878         switch(vid.renderpath)
8879         {
8880         case RENDERPATH_GL11:
8881         case RENDERPATH_GL13:
8882         case RENDERPATH_GL20:
8883         case RENDERPATH_CGGL:
8884                 break;
8885         case RENDERPATH_D3D9:
8886         case RENDERPATH_D3D10:
8887         case RENDERPATH_D3D11:
8888                 {
8889                         int i;
8890                         for (i = 0;i < 4;i++)
8891                         {
8892                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8893                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8894                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8895                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8896                         }
8897                 }
8898                 break;
8899         }
8900
8901         if (r_hdr.integer || r_bloom.integer)
8902         {
8903                 r_bloomstate.enabled = true;
8904                 r_bloomstate.hdr = r_hdr.integer != 0;
8905         }
8906
8907         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);
8908 }
8909
8910 void R_Bloom_CopyBloomTexture(float colorscale)
8911 {
8912         r_refdef.stats.bloom++;
8913
8914         // scale down screen texture to the bloom texture size
8915         CHECKGLERROR
8916         R_SetViewport(&r_bloomstate.viewport);
8917         GL_BlendFunc(GL_ONE, GL_ZERO);
8918         GL_Color(colorscale, colorscale, colorscale, 1);
8919         // 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...
8920         switch(vid.renderpath)
8921         {
8922         case RENDERPATH_GL11:
8923         case RENDERPATH_GL13:
8924         case RENDERPATH_GL20:
8925         case RENDERPATH_CGGL:
8926                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8927                 break;
8928         case RENDERPATH_D3D9:
8929         case RENDERPATH_D3D10:
8930         case RENDERPATH_D3D11:
8931                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8932                 break;
8933         }
8934         // TODO: do boxfilter scale-down in shader?
8935         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8936         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8937         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8938
8939         // we now have a bloom image in the framebuffer
8940         // copy it into the bloom image texture for later processing
8941         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);
8942         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8943 }
8944
8945 void R_Bloom_CopyHDRTexture(void)
8946 {
8947         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);
8948         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8949 }
8950
8951 void R_Bloom_MakeTexture(void)
8952 {
8953         int x, range, dir;
8954         float xoffset, yoffset, r, brighten;
8955
8956         r_refdef.stats.bloom++;
8957
8958         R_ResetViewRendering2D();
8959
8960         // we have a bloom image in the framebuffer
8961         CHECKGLERROR
8962         R_SetViewport(&r_bloomstate.viewport);
8963
8964         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8965         {
8966                 x *= 2;
8967                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8968                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8969                 GL_Color(r,r,r,1);
8970                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8971                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8972                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8973                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8974
8975                 // copy the vertically blurred bloom view to a texture
8976                 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);
8977                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8978         }
8979
8980         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8981         brighten = r_bloom_brighten.value;
8982         if (r_hdr.integer)
8983                 brighten *= r_hdr_range.value;
8984         brighten = sqrt(brighten);
8985         if(range >= 1)
8986                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8987         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8988
8989         for (dir = 0;dir < 2;dir++)
8990         {
8991                 // blend on at multiple vertical offsets to achieve a vertical blur
8992                 // TODO: do offset blends using GLSL
8993                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8994                 GL_BlendFunc(GL_ONE, GL_ZERO);
8995                 for (x = -range;x <= range;x++)
8996                 {
8997                         if (!dir){xoffset = 0;yoffset = x;}
8998                         else {xoffset = x;yoffset = 0;}
8999                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9000                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9001                         // compute a texcoord array with the specified x and y offset
9002                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9003                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9004                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9005                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9006                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9007                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9008                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9009                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9010                         // this r value looks like a 'dot' particle, fading sharply to
9011                         // black at the edges
9012                         // (probably not realistic but looks good enough)
9013                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9014                         //r = brighten/(range*2+1);
9015                         r = brighten / (range * 2 + 1);
9016                         if(range >= 1)
9017                                 r *= (1 - x*x/(float)(range*range));
9018                         GL_Color(r, r, r, 1);
9019                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9020                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9021                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9022                         GL_BlendFunc(GL_ONE, GL_ONE);
9023                 }
9024
9025                 // copy the vertically blurred bloom view to a texture
9026                 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);
9027                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9028         }
9029 }
9030
9031 void R_HDR_RenderBloomTexture(void)
9032 {
9033         int oldwidth, oldheight;
9034         float oldcolorscale;
9035
9036         oldcolorscale = r_refdef.view.colorscale;
9037         oldwidth = r_refdef.view.width;
9038         oldheight = r_refdef.view.height;
9039         r_refdef.view.width = r_bloomstate.bloomwidth;
9040         r_refdef.view.height = r_bloomstate.bloomheight;
9041
9042         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9043         // TODO: add exposure compensation features
9044         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9045
9046         r_refdef.view.showdebug = false;
9047         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9048
9049         R_ResetViewRendering3D();
9050
9051         R_ClearScreen(r_refdef.fogenabled);
9052         if (r_timereport_active)
9053                 R_TimeReport("HDRclear");
9054
9055         R_View_Update();
9056         if (r_timereport_active)
9057                 R_TimeReport("visibility");
9058
9059         // only do secondary renders with HDR if r_hdr is 2 or higher
9060         r_waterstate.numwaterplanes = 0;
9061         if (r_waterstate.enabled && r_hdr.integer >= 2)
9062                 R_RenderWaterPlanes();
9063
9064         r_refdef.view.showdebug = true;
9065         R_RenderScene();
9066         r_waterstate.numwaterplanes = 0;
9067
9068         R_ResetViewRendering2D();
9069
9070         R_Bloom_CopyHDRTexture();
9071         R_Bloom_MakeTexture();
9072
9073         // restore the view settings
9074         r_refdef.view.width = oldwidth;
9075         r_refdef.view.height = oldheight;
9076         r_refdef.view.colorscale = oldcolorscale;
9077
9078         R_ResetViewRendering3D();
9079
9080         R_ClearScreen(r_refdef.fogenabled);
9081         if (r_timereport_active)
9082                 R_TimeReport("viewclear");
9083 }
9084
9085 static void R_BlendView(void)
9086 {
9087         unsigned int permutation;
9088         float uservecs[4][4];
9089
9090         switch (vid.renderpath)
9091         {
9092         case RENDERPATH_GL20:
9093         case RENDERPATH_CGGL:
9094         case RENDERPATH_D3D9:
9095         case RENDERPATH_D3D10:
9096         case RENDERPATH_D3D11:
9097                 permutation =
9098                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9099                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9100                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9101                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9102                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9103
9104                 if (r_bloomstate.texture_screen)
9105                 {
9106                         // make sure the buffer is available
9107                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9108
9109                         R_ResetViewRendering2D();
9110
9111                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9112                         {
9113                                 // declare variables
9114                                 float speed;
9115                                 static float avgspeed;
9116
9117                                 speed = VectorLength(cl.movement_velocity);
9118
9119                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9120                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9121
9122                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9123                                 speed = bound(0, speed, 1);
9124                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9125
9126                                 // calculate values into a standard alpha
9127                                 cl.motionbluralpha = 1 - exp(-
9128                                                 (
9129                                                  (r_motionblur.value * speed / 80)
9130                                                  +
9131                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9132                                                 )
9133                                                 /
9134                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9135                                            );
9136
9137                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9138                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9139                                 // apply the blur
9140                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9141                                 {
9142                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9143                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9144                                         switch(vid.renderpath)
9145                                         {
9146                                         case RENDERPATH_GL11:
9147                                         case RENDERPATH_GL13:
9148                                         case RENDERPATH_GL20:
9149                                         case RENDERPATH_CGGL:
9150                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9151                                                 break;
9152                                         case RENDERPATH_D3D9:
9153                                         case RENDERPATH_D3D10:
9154                                         case RENDERPATH_D3D11:
9155                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9156                                                 break;
9157                                         }
9158                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9159                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9160                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9161                                 }
9162                         }
9163
9164                         // copy view into the screen texture
9165                         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);
9166                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9167                 }
9168                 else if (!r_bloomstate.texture_bloom)
9169                 {
9170                         // we may still have to do view tint...
9171                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9172                         {
9173                                 // apply a color tint to the whole view
9174                                 R_ResetViewRendering2D();
9175                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9176                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9177                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9178                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9179                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9180                         }
9181                         break; // no screen processing, no bloom, skip it
9182                 }
9183
9184                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9185                 {
9186                         // render simple bloom effect
9187                         // copy the screen and shrink it and darken it for the bloom process
9188                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9189                         // make the bloom texture
9190                         R_Bloom_MakeTexture();
9191                 }
9192
9193 #if _MSC_VER >= 1400
9194 #define sscanf sscanf_s
9195 #endif
9196                 memset(uservecs, 0, sizeof(uservecs));
9197                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9198                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9199                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9200                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9201
9202                 R_ResetViewRendering2D();
9203                 GL_Color(1, 1, 1, 1);
9204                 GL_BlendFunc(GL_ONE, GL_ZERO);
9205
9206                 switch(vid.renderpath)
9207                 {
9208                 case RENDERPATH_GL20:
9209                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9210                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9211                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9212                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9213                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9214                         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]);
9215                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9216                         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]);
9217                         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]);
9218                         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]);
9219                         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]);
9220                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9221                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9222                         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);
9223                         break;
9224                 case RENDERPATH_CGGL:
9225 #ifdef SUPPORTCG
9226                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9227                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9228                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9229                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9230                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9231                         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
9232                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9233                         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
9234                         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
9235                         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
9236                         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
9237                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9238                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9239                         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);
9240 #endif
9241                         break;
9242                 case RENDERPATH_D3D9:
9243 #ifdef SUPPORTD3D
9244                         // 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...
9245                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9246                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9247                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9248                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9249                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9250                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9251                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9252                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9253                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9254                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9255                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9256                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9257                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9258                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9259 #endif
9260                         break;
9261                 case RENDERPATH_D3D10:
9262                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9263                         break;
9264                 case RENDERPATH_D3D11:
9265                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9266                         break;
9267                 default:
9268                         break;
9269                 }
9270                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9271                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9272                 break;
9273         case RENDERPATH_GL13:
9274         case RENDERPATH_GL11:
9275                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9276                 {
9277                         // apply a color tint to the whole view
9278                         R_ResetViewRendering2D();
9279                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9280                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9281                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9282                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9283                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9284                 }
9285                 break;
9286         }
9287 }
9288
9289 matrix4x4_t r_waterscrollmatrix;
9290
9291 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9292 {
9293         if (r_refdef.fog_density)
9294         {
9295                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9296                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9297                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9298
9299                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9300                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9301                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9302                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9303
9304                 {
9305                         vec3_t fogvec;
9306                         VectorCopy(r_refdef.fogcolor, fogvec);
9307                         //   color.rgb *= ContrastBoost * SceneBrightness;
9308                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9309                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9310                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9311                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9312                 }
9313         }
9314 }
9315
9316 void R_UpdateVariables(void)
9317 {
9318         R_Textures_Frame();
9319
9320         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9321
9322         r_refdef.farclip = r_farclip_base.value;
9323         if (r_refdef.scene.worldmodel)
9324                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9325         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9326
9327         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9328                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9329         r_refdef.polygonfactor = 0;
9330         r_refdef.polygonoffset = 0;
9331         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9332         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9333
9334         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9335         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9336         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9337         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9338         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9339         if (r_showsurfaces.integer)
9340         {
9341                 r_refdef.scene.rtworld = false;
9342                 r_refdef.scene.rtworldshadows = false;
9343                 r_refdef.scene.rtdlight = false;
9344                 r_refdef.scene.rtdlightshadows = false;
9345                 r_refdef.lightmapintensity = 0;
9346         }
9347
9348         if (gamemode == GAME_NEHAHRA)
9349         {
9350                 if (gl_fogenable.integer)
9351                 {
9352                         r_refdef.oldgl_fogenable = true;
9353                         r_refdef.fog_density = gl_fogdensity.value;
9354                         r_refdef.fog_red = gl_fogred.value;
9355                         r_refdef.fog_green = gl_foggreen.value;
9356                         r_refdef.fog_blue = gl_fogblue.value;
9357                         r_refdef.fog_alpha = 1;
9358                         r_refdef.fog_start = 0;
9359                         r_refdef.fog_end = gl_skyclip.value;
9360                         r_refdef.fog_height = 1<<30;
9361                         r_refdef.fog_fadedepth = 128;
9362                 }
9363                 else if (r_refdef.oldgl_fogenable)
9364                 {
9365                         r_refdef.oldgl_fogenable = false;
9366                         r_refdef.fog_density = 0;
9367                         r_refdef.fog_red = 0;
9368                         r_refdef.fog_green = 0;
9369                         r_refdef.fog_blue = 0;
9370                         r_refdef.fog_alpha = 0;
9371                         r_refdef.fog_start = 0;
9372                         r_refdef.fog_end = 0;
9373                         r_refdef.fog_height = 1<<30;
9374                         r_refdef.fog_fadedepth = 128;
9375                 }
9376         }
9377
9378         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9379         r_refdef.fog_start = max(0, r_refdef.fog_start);
9380         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9381
9382         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9383
9384         if (r_refdef.fog_density && r_drawfog.integer)
9385         {
9386                 r_refdef.fogenabled = true;
9387                 // this is the point where the fog reaches 0.9986 alpha, which we
9388                 // consider a good enough cutoff point for the texture
9389                 // (0.9986 * 256 == 255.6)
9390                 if (r_fog_exp2.integer)
9391                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9392                 else
9393                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9394                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9395                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9396                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9397                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9398                         R_BuildFogHeightTexture();
9399                 // fog color was already set
9400                 // update the fog texture
9401                 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)
9402                         R_BuildFogTexture();
9403                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9404                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9405         }
9406         else
9407                 r_refdef.fogenabled = false;
9408
9409         switch(vid.renderpath)
9410         {
9411         case RENDERPATH_GL20:
9412         case RENDERPATH_CGGL:
9413         case RENDERPATH_D3D9:
9414         case RENDERPATH_D3D10:
9415         case RENDERPATH_D3D11:
9416                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9417                 {
9418                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9419                         {
9420                                 // build GLSL gamma texture
9421 #define RAMPWIDTH 256
9422                                 unsigned short ramp[RAMPWIDTH * 3];
9423                                 unsigned char rampbgr[RAMPWIDTH][4];
9424                                 int i;
9425
9426                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9427
9428                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9429                                 for(i = 0; i < RAMPWIDTH; ++i)
9430                                 {
9431                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9432                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9433                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9434                                         rampbgr[i][3] = 0;
9435                                 }
9436                                 if (r_texture_gammaramps)
9437                                 {
9438                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9439                                 }
9440                                 else
9441                                 {
9442                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
9443                                 }
9444                         }
9445                 }
9446                 else
9447                 {
9448                         // remove GLSL gamma texture
9449                 }
9450                 break;
9451         case RENDERPATH_GL13:
9452         case RENDERPATH_GL11:
9453                 break;
9454         }
9455 }
9456
9457 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9458 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9459 /*
9460 ================
9461 R_SelectScene
9462 ================
9463 */
9464 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9465         if( scenetype != r_currentscenetype ) {
9466                 // store the old scenetype
9467                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9468                 r_currentscenetype = scenetype;
9469                 // move in the new scene
9470                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9471         }
9472 }
9473
9474 /*
9475 ================
9476 R_GetScenePointer
9477 ================
9478 */
9479 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9480 {
9481         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9482         if( scenetype == r_currentscenetype ) {
9483                 return &r_refdef.scene;
9484         } else {
9485                 return &r_scenes_store[ scenetype ];
9486         }
9487 }
9488
9489 /*
9490 ================
9491 R_RenderView
9492 ================
9493 */
9494 void R_RenderView(void)
9495 {
9496         if (r_timereport_active)
9497                 R_TimeReport("start");
9498         r_textureframe++; // used only by R_GetCurrentTexture
9499         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9500
9501         if (!r_drawentities.integer)
9502                 r_refdef.scene.numentities = 0;
9503
9504         R_AnimCache_ClearCache();
9505         R_FrameData_NewFrame();
9506
9507         if (r_refdef.view.isoverlay)
9508         {
9509                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9510                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9511                 R_TimeReport("depthclear");
9512
9513                 r_refdef.view.showdebug = false;
9514
9515                 r_waterstate.enabled = false;
9516                 r_waterstate.numwaterplanes = 0;
9517
9518                 R_RenderScene();
9519
9520                 CHECKGLERROR
9521                 return;
9522         }
9523
9524         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9525                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9526
9527         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9528
9529         R_RenderView_UpdateViewVectors();
9530
9531         R_Shadow_UpdateWorldLightSelection();
9532
9533         R_Bloom_StartFrame();
9534         R_Water_StartFrame();
9535
9536         CHECKGLERROR
9537         if (r_timereport_active)
9538                 R_TimeReport("viewsetup");
9539
9540         R_ResetViewRendering3D();
9541
9542         if (r_refdef.view.clear || r_refdef.fogenabled)
9543         {
9544                 R_ClearScreen(r_refdef.fogenabled);
9545                 if (r_timereport_active)
9546                         R_TimeReport("viewclear");
9547         }
9548         r_refdef.view.clear = true;
9549
9550         // this produces a bloom texture to be used in R_BlendView() later
9551         if (r_hdr.integer && r_bloomstate.bloomwidth)
9552         {
9553                 R_HDR_RenderBloomTexture();
9554                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9555                 r_textureframe++; // used only by R_GetCurrentTexture
9556         }
9557
9558         r_refdef.view.showdebug = true;
9559
9560         R_View_Update();
9561         if (r_timereport_active)
9562                 R_TimeReport("visibility");
9563
9564         r_waterstate.numwaterplanes = 0;
9565         if (r_waterstate.enabled)
9566                 R_RenderWaterPlanes();
9567
9568         R_RenderScene();
9569         r_waterstate.numwaterplanes = 0;
9570
9571         R_BlendView();
9572         if (r_timereport_active)
9573                 R_TimeReport("blendview");
9574
9575         GL_Scissor(0, 0, vid.width, vid.height);
9576         GL_ScissorTest(false);
9577         CHECKGLERROR
9578 }
9579
9580 void R_RenderWaterPlanes(void)
9581 {
9582         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9583         {
9584                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9585                 if (r_timereport_active)
9586                         R_TimeReport("waterworld");
9587         }
9588
9589         // don't let sound skip if going slow
9590         if (r_refdef.scene.extraupdate)
9591                 S_ExtraUpdate ();
9592
9593         R_DrawModelsAddWaterPlanes();
9594         if (r_timereport_active)
9595                 R_TimeReport("watermodels");
9596
9597         if (r_waterstate.numwaterplanes)
9598         {
9599                 R_Water_ProcessPlanes();
9600                 if (r_timereport_active)
9601                         R_TimeReport("waterscenes");
9602         }
9603 }
9604
9605 extern void R_DrawLightningBeams (void);
9606 extern void VM_CL_AddPolygonsToMeshQueue (void);
9607 extern void R_DrawPortals (void);
9608 extern cvar_t cl_locs_show;
9609 static void R_DrawLocs(void);
9610 static void R_DrawEntityBBoxes(void);
9611 static void R_DrawModelDecals(void);
9612 extern void R_DrawModelShadows(void);
9613 extern void R_DrawModelShadowMaps(void);
9614 extern cvar_t cl_decals_newsystem;
9615 extern qboolean r_shadow_usingdeferredprepass;
9616 void R_RenderScene(void)
9617 {
9618         qboolean shadowmapping = false;
9619
9620         if (r_timereport_active)
9621                 R_TimeReport("beginscene");
9622
9623         r_refdef.stats.renders++;
9624
9625         R_UpdateFogColor();
9626
9627         // don't let sound skip if going slow
9628         if (r_refdef.scene.extraupdate)
9629                 S_ExtraUpdate ();
9630
9631         R_MeshQueue_BeginScene();
9632
9633         R_SkyStartFrame();
9634
9635         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);
9636
9637         if (r_timereport_active)
9638                 R_TimeReport("skystartframe");
9639
9640         if (cl.csqc_vidvars.drawworld)
9641         {
9642                 // don't let sound skip if going slow
9643                 if (r_refdef.scene.extraupdate)
9644                         S_ExtraUpdate ();
9645
9646                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9647                 {
9648                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9649                         if (r_timereport_active)
9650                                 R_TimeReport("worldsky");
9651                 }
9652
9653                 if (R_DrawBrushModelsSky() && r_timereport_active)
9654                         R_TimeReport("bmodelsky");
9655
9656                 if (skyrendermasked && skyrenderlater)
9657                 {
9658                         // we have to force off the water clipping plane while rendering sky
9659                         R_SetupView(false);
9660                         R_Sky();
9661                         R_SetupView(true);
9662                         if (r_timereport_active)
9663                                 R_TimeReport("sky");
9664                 }
9665         }
9666
9667         R_AnimCache_CacheVisibleEntities();
9668         if (r_timereport_active)
9669                 R_TimeReport("animation");
9670
9671         R_Shadow_PrepareLights();
9672         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9673                 R_Shadow_PrepareModelShadows();
9674         if (r_timereport_active)
9675                 R_TimeReport("preparelights");
9676
9677         if (R_Shadow_ShadowMappingEnabled())
9678                 shadowmapping = true;
9679
9680         if (r_shadow_usingdeferredprepass)
9681                 R_Shadow_DrawPrepass();
9682
9683         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9684         {
9685                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9686                 if (r_timereport_active)
9687                         R_TimeReport("worlddepth");
9688         }
9689         if (r_depthfirst.integer >= 2)
9690         {
9691                 R_DrawModelsDepth();
9692                 if (r_timereport_active)
9693                         R_TimeReport("modeldepth");
9694         }
9695
9696         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9697         {
9698                 R_DrawModelShadowMaps();
9699                 R_ResetViewRendering3D();
9700                 // don't let sound skip if going slow
9701                 if (r_refdef.scene.extraupdate)
9702                         S_ExtraUpdate ();
9703         }
9704
9705         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9706         {
9707                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9708                 if (r_timereport_active)
9709                         R_TimeReport("world");
9710         }
9711
9712         // don't let sound skip if going slow
9713         if (r_refdef.scene.extraupdate)
9714                 S_ExtraUpdate ();
9715
9716         R_DrawModels();
9717         if (r_timereport_active)
9718                 R_TimeReport("models");
9719
9720         // don't let sound skip if going slow
9721         if (r_refdef.scene.extraupdate)
9722                 S_ExtraUpdate ();
9723
9724         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9725         {
9726                 R_DrawModelShadows();
9727                 R_ResetViewRendering3D();
9728                 // don't let sound skip if going slow
9729                 if (r_refdef.scene.extraupdate)
9730                         S_ExtraUpdate ();
9731         }
9732
9733         if (!r_shadow_usingdeferredprepass)
9734         {
9735                 R_Shadow_DrawLights();
9736                 if (r_timereport_active)
9737                         R_TimeReport("rtlights");
9738         }
9739
9740         // don't let sound skip if going slow
9741         if (r_refdef.scene.extraupdate)
9742                 S_ExtraUpdate ();
9743
9744         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9745         {
9746                 R_DrawModelShadows();
9747                 R_ResetViewRendering3D();
9748                 // don't let sound skip if going slow
9749                 if (r_refdef.scene.extraupdate)
9750                         S_ExtraUpdate ();
9751         }
9752
9753         if (cl.csqc_vidvars.drawworld)
9754         {
9755                 if (cl_decals_newsystem.integer)
9756                 {
9757                         R_DrawModelDecals();
9758                         if (r_timereport_active)
9759                                 R_TimeReport("modeldecals");
9760                 }
9761                 else
9762                 {
9763                         R_DrawDecals();
9764                         if (r_timereport_active)
9765                                 R_TimeReport("decals");
9766                 }
9767
9768                 R_DrawParticles();
9769                 if (r_timereport_active)
9770                         R_TimeReport("particles");
9771
9772                 R_DrawExplosions();
9773                 if (r_timereport_active)
9774                         R_TimeReport("explosions");
9775
9776                 R_DrawLightningBeams();
9777                 if (r_timereport_active)
9778                         R_TimeReport("lightning");
9779         }
9780
9781         VM_CL_AddPolygonsToMeshQueue();
9782
9783         if (r_refdef.view.showdebug)
9784         {
9785                 if (cl_locs_show.integer)
9786                 {
9787                         R_DrawLocs();
9788                         if (r_timereport_active)
9789                                 R_TimeReport("showlocs");
9790                 }
9791
9792                 if (r_drawportals.integer)
9793                 {
9794                         R_DrawPortals();
9795                         if (r_timereport_active)
9796                                 R_TimeReport("portals");
9797                 }
9798
9799                 if (r_showbboxes.value > 0)
9800                 {
9801                         R_DrawEntityBBoxes();
9802                         if (r_timereport_active)
9803                                 R_TimeReport("bboxes");
9804                 }
9805         }
9806
9807         R_MeshQueue_RenderTransparent();
9808         if (r_timereport_active)
9809                 R_TimeReport("drawtrans");
9810
9811         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))
9812         {
9813                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9814                 if (r_timereport_active)
9815                         R_TimeReport("worlddebug");
9816                 R_DrawModelsDebug();
9817                 if (r_timereport_active)
9818                         R_TimeReport("modeldebug");
9819         }
9820
9821         if (cl.csqc_vidvars.drawworld)
9822         {
9823                 R_Shadow_DrawCoronas();
9824                 if (r_timereport_active)
9825                         R_TimeReport("coronas");
9826         }
9827
9828         // don't let sound skip if going slow
9829         if (r_refdef.scene.extraupdate)
9830                 S_ExtraUpdate ();
9831
9832         R_ResetViewRendering2D();
9833 }
9834
9835 static const unsigned short bboxelements[36] =
9836 {
9837         5, 1, 3, 5, 3, 7,
9838         6, 2, 0, 6, 0, 4,
9839         7, 3, 2, 7, 2, 6,
9840         4, 0, 1, 4, 1, 5,
9841         4, 5, 7, 4, 7, 6,
9842         1, 0, 2, 1, 2, 3,
9843 };
9844
9845 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9846 {
9847         int i;
9848         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9849
9850         RSurf_ActiveWorldEntity();
9851
9852         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9853         GL_DepthMask(false);
9854         GL_DepthRange(0, 1);
9855         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9856         R_Mesh_ResetTextureState();
9857
9858         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9859         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9860         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9861         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9862         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9863         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9864         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9865         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9866         R_FillColors(color4f, 8, cr, cg, cb, ca);
9867         if (r_refdef.fogenabled)
9868         {
9869                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9870                 {
9871                         f1 = RSurf_FogVertex(v);
9872                         f2 = 1 - f1;
9873                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9874                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9875                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9876                 }
9877         }
9878         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9879         R_Mesh_ResetTextureState();
9880         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9881         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9882 }
9883
9884 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9885 {
9886         int i;
9887         float color[4];
9888         prvm_edict_t *edict;
9889         prvm_prog_t *prog_save = prog;
9890
9891         // this function draws bounding boxes of server entities
9892         if (!sv.active)
9893                 return;
9894
9895         GL_CullFace(GL_NONE);
9896         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9897
9898         prog = 0;
9899         SV_VM_Begin();
9900         for (i = 0;i < numsurfaces;i++)
9901         {
9902                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9903                 switch ((int)edict->fields.server->solid)
9904                 {
9905                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9906                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9907                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9908                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9909                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9910                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9911                 }
9912                 color[3] *= r_showbboxes.value;
9913                 color[3] = bound(0, color[3], 1);
9914                 GL_DepthTest(!r_showdisabledepthtest.integer);
9915                 GL_CullFace(r_refdef.view.cullface_front);
9916                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9917         }
9918         SV_VM_End();
9919         prog = prog_save;
9920 }
9921
9922 static void R_DrawEntityBBoxes(void)
9923 {
9924         int i;
9925         prvm_edict_t *edict;
9926         vec3_t center;
9927         prvm_prog_t *prog_save = prog;
9928
9929         // this function draws bounding boxes of server entities
9930         if (!sv.active)
9931                 return;
9932
9933         prog = 0;
9934         SV_VM_Begin();
9935         for (i = 0;i < prog->num_edicts;i++)
9936         {
9937                 edict = PRVM_EDICT_NUM(i);
9938                 if (edict->priv.server->free)
9939                         continue;
9940                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9941                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9942                         continue;
9943                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9944                         continue;
9945                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9946                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9947         }
9948         SV_VM_End();
9949         prog = prog_save;
9950 }
9951
9952 static const int nomodelelement3i[24] =
9953 {
9954         5, 2, 0,
9955         5, 1, 2,
9956         5, 0, 3,
9957         5, 3, 1,
9958         0, 2, 4,
9959         2, 1, 4,
9960         3, 0, 4,
9961         1, 3, 4
9962 };
9963
9964 static const unsigned short nomodelelement3s[24] =
9965 {
9966         5, 2, 0,
9967         5, 1, 2,
9968         5, 0, 3,
9969         5, 3, 1,
9970         0, 2, 4,
9971         2, 1, 4,
9972         3, 0, 4,
9973         1, 3, 4
9974 };
9975
9976 static const float nomodelvertex3f[6*3] =
9977 {
9978         -16,   0,   0,
9979          16,   0,   0,
9980           0, -16,   0,
9981           0,  16,   0,
9982           0,   0, -16,
9983           0,   0,  16
9984 };
9985
9986 static const float nomodelcolor4f[6*4] =
9987 {
9988         0.0f, 0.0f, 0.5f, 1.0f,
9989         0.0f, 0.0f, 0.5f, 1.0f,
9990         0.0f, 0.5f, 0.0f, 1.0f,
9991         0.0f, 0.5f, 0.0f, 1.0f,
9992         0.5f, 0.0f, 0.0f, 1.0f,
9993         0.5f, 0.0f, 0.0f, 1.0f
9994 };
9995
9996 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9997 {
9998         int i;
9999         float f1, f2, *c;
10000         float color4f[6*4];
10001
10002         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);
10003
10004         // this is only called once per entity so numsurfaces is always 1, and
10005         // surfacelist is always {0}, so this code does not handle batches
10006
10007         if (rsurface.ent_flags & RENDER_ADDITIVE)
10008         {
10009                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10010                 GL_DepthMask(false);
10011         }
10012         else if (rsurface.colormod[3] < 1)
10013         {
10014                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10015                 GL_DepthMask(false);
10016         }
10017         else
10018         {
10019                 GL_BlendFunc(GL_ONE, GL_ZERO);
10020                 GL_DepthMask(true);
10021         }
10022         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10023         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10024         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10025         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10026         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10027         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10028         for (i = 0, c = color4f;i < 6;i++, c += 4)
10029         {
10030                 c[0] *= rsurface.colormod[0];
10031                 c[1] *= rsurface.colormod[1];
10032                 c[2] *= rsurface.colormod[2];
10033                 c[3] *= rsurface.colormod[3];
10034         }
10035         if (r_refdef.fogenabled)
10036         {
10037                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10038                 {
10039                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10040                         f2 = 1 - f1;
10041                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10042                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10043                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10044                 }
10045         }
10046         R_Mesh_ResetTextureState();
10047         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10048         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10049 }
10050
10051 void R_DrawNoModel(entity_render_t *ent)
10052 {
10053         vec3_t org;
10054         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10055         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10056                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10057         else
10058                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10059 }
10060
10061 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10062 {
10063         vec3_t right1, right2, diff, normal;
10064
10065         VectorSubtract (org2, org1, normal);
10066
10067         // calculate 'right' vector for start
10068         VectorSubtract (r_refdef.view.origin, org1, diff);
10069         CrossProduct (normal, diff, right1);
10070         VectorNormalize (right1);
10071
10072         // calculate 'right' vector for end
10073         VectorSubtract (r_refdef.view.origin, org2, diff);
10074         CrossProduct (normal, diff, right2);
10075         VectorNormalize (right2);
10076
10077         vert[ 0] = org1[0] + width * right1[0];
10078         vert[ 1] = org1[1] + width * right1[1];
10079         vert[ 2] = org1[2] + width * right1[2];
10080         vert[ 3] = org1[0] - width * right1[0];
10081         vert[ 4] = org1[1] - width * right1[1];
10082         vert[ 5] = org1[2] - width * right1[2];
10083         vert[ 6] = org2[0] - width * right2[0];
10084         vert[ 7] = org2[1] - width * right2[1];
10085         vert[ 8] = org2[2] - width * right2[2];
10086         vert[ 9] = org2[0] + width * right2[0];
10087         vert[10] = org2[1] + width * right2[1];
10088         vert[11] = org2[2] + width * right2[2];
10089 }
10090
10091 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)
10092 {
10093         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10094         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10095         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10096         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10097         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10098         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10099         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10100         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10101         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10102         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10103         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10104         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10105 }
10106
10107 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10108 {
10109         int i;
10110         float *vertex3f;
10111         float v[3];
10112         VectorSet(v, x, y, z);
10113         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10114                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10115                         break;
10116         if (i == mesh->numvertices)
10117         {
10118                 if (mesh->numvertices < mesh->maxvertices)
10119                 {
10120                         VectorCopy(v, vertex3f);
10121                         mesh->numvertices++;
10122                 }
10123                 return mesh->numvertices;
10124         }
10125         else
10126                 return i;
10127 }
10128
10129 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10130 {
10131         int i;
10132         int *e, element[3];
10133         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10134         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10135         e = mesh->element3i + mesh->numtriangles * 3;
10136         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10137         {
10138                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10139                 if (mesh->numtriangles < mesh->maxtriangles)
10140                 {
10141                         *e++ = element[0];
10142                         *e++ = element[1];
10143                         *e++ = element[2];
10144                         mesh->numtriangles++;
10145                 }
10146                 element[1] = element[2];
10147         }
10148 }
10149
10150 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10151 {
10152         int i;
10153         int *e, element[3];
10154         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10155         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10156         e = mesh->element3i + mesh->numtriangles * 3;
10157         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10158         {
10159                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10160                 if (mesh->numtriangles < mesh->maxtriangles)
10161                 {
10162                         *e++ = element[0];
10163                         *e++ = element[1];
10164                         *e++ = element[2];
10165                         mesh->numtriangles++;
10166                 }
10167                 element[1] = element[2];
10168         }
10169 }
10170
10171 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10172 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10173 {
10174         int planenum, planenum2;
10175         int w;
10176         int tempnumpoints;
10177         mplane_t *plane, *plane2;
10178         double maxdist;
10179         double temppoints[2][256*3];
10180         // figure out how large a bounding box we need to properly compute this brush
10181         maxdist = 0;
10182         for (w = 0;w < numplanes;w++)
10183                 maxdist = max(maxdist, fabs(planes[w].dist));
10184         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10185         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10186         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10187         {
10188                 w = 0;
10189                 tempnumpoints = 4;
10190                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10191                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10192                 {
10193                         if (planenum2 == planenum)
10194                                 continue;
10195                         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);
10196                         w = !w;
10197                 }
10198                 if (tempnumpoints < 3)
10199                         continue;
10200                 // generate elements forming a triangle fan for this polygon
10201                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10202         }
10203 }
10204
10205 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)
10206 {
10207         texturelayer_t *layer;
10208         layer = t->currentlayers + t->currentnumlayers++;
10209         layer->type = type;
10210         layer->depthmask = depthmask;
10211         layer->blendfunc1 = blendfunc1;
10212         layer->blendfunc2 = blendfunc2;
10213         layer->texture = texture;
10214         layer->texmatrix = *matrix;
10215         layer->color[0] = r;
10216         layer->color[1] = g;
10217         layer->color[2] = b;
10218         layer->color[3] = a;
10219 }
10220
10221 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10222 {
10223         if(parms[0] == 0 && parms[1] == 0)
10224                 return false;
10225         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10226                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10227                         return false;
10228         return true;
10229 }
10230
10231 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10232 {
10233         double index, f;
10234         index = parms[2] + r_refdef.scene.time * parms[3];
10235         index -= floor(index);
10236         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10237         {
10238         default:
10239         case Q3WAVEFUNC_NONE:
10240         case Q3WAVEFUNC_NOISE:
10241         case Q3WAVEFUNC_COUNT:
10242                 f = 0;
10243                 break;
10244         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10245         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10246         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10247         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10248         case Q3WAVEFUNC_TRIANGLE:
10249                 index *= 4;
10250                 f = index - floor(index);
10251                 if (index < 1)
10252                         f = f;
10253                 else if (index < 2)
10254                         f = 1 - f;
10255                 else if (index < 3)
10256                         f = -f;
10257                 else
10258                         f = -(1 - f);
10259                 break;
10260         }
10261         f = parms[0] + parms[1] * f;
10262         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10263                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10264         return (float) f;
10265 }
10266
10267 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10268 {
10269         int w, h, idx;
10270         float f;
10271         float tcmat[12];
10272         matrix4x4_t matrix, temp;
10273         switch(tcmod->tcmod)
10274         {
10275                 case Q3TCMOD_COUNT:
10276                 case Q3TCMOD_NONE:
10277                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10278                                 matrix = r_waterscrollmatrix;
10279                         else
10280                                 matrix = identitymatrix;
10281                         break;
10282                 case Q3TCMOD_ENTITYTRANSLATE:
10283                         // this is used in Q3 to allow the gamecode to control texcoord
10284                         // scrolling on the entity, which is not supported in darkplaces yet.
10285                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10286                         break;
10287                 case Q3TCMOD_ROTATE:
10288                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10289                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10290                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10291                         break;
10292                 case Q3TCMOD_SCALE:
10293                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10294                         break;
10295                 case Q3TCMOD_SCROLL:
10296                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10297                         break;
10298                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10299                         w = (int) tcmod->parms[0];
10300                         h = (int) tcmod->parms[1];
10301                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10302                         f = f - floor(f);
10303                         idx = (int) floor(f * w * h);
10304                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10305                         break;
10306                 case Q3TCMOD_STRETCH:
10307                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10308                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10309                         break;
10310                 case Q3TCMOD_TRANSFORM:
10311                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10312                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10313                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10314                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10315                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10316                         break;
10317                 case Q3TCMOD_TURBULENT:
10318                         // this is handled in the RSurf_PrepareVertices function
10319                         matrix = identitymatrix;
10320                         break;
10321         }
10322         temp = *texmatrix;
10323         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10324 }
10325
10326 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10327 {
10328         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10329         char name[MAX_QPATH];
10330         skinframe_t *skinframe;
10331         unsigned char pixels[296*194];
10332         strlcpy(cache->name, skinname, sizeof(cache->name));
10333         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10334         if (developer_loading.integer)
10335                 Con_Printf("loading %s\n", name);
10336         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10337         if (!skinframe || !skinframe->base)
10338         {
10339                 unsigned char *f;
10340                 fs_offset_t filesize;
10341                 skinframe = NULL;
10342                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10343                 if (f)
10344                 {
10345                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10346                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10347                         Mem_Free(f);
10348                 }
10349         }
10350         cache->skinframe = skinframe;
10351 }
10352
10353 texture_t *R_GetCurrentTexture(texture_t *t)
10354 {
10355         int i;
10356         const entity_render_t *ent = rsurface.entity;
10357         dp_model_t *model = ent->model;
10358         q3shaderinfo_layer_tcmod_t *tcmod;
10359
10360         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10361                 return t->currentframe;
10362         t->update_lastrenderframe = r_textureframe;
10363         t->update_lastrenderentity = (void *)ent;
10364
10365         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10366                 t->camera_entity = ent->entitynumber;
10367         else
10368                 t->camera_entity = 0;
10369
10370         // switch to an alternate material if this is a q1bsp animated material
10371         {
10372                 texture_t *texture = t;
10373                 int s = rsurface.ent_skinnum;
10374                 if ((unsigned int)s >= (unsigned int)model->numskins)
10375                         s = 0;
10376                 if (model->skinscenes)
10377                 {
10378                         if (model->skinscenes[s].framecount > 1)
10379                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10380                         else
10381                                 s = model->skinscenes[s].firstframe;
10382                 }
10383                 if (s > 0)
10384                         t = t + s * model->num_surfaces;
10385                 if (t->animated)
10386                 {
10387                         // use an alternate animation if the entity's frame is not 0,
10388                         // and only if the texture has an alternate animation
10389                         if (rsurface.ent_alttextures && t->anim_total[1])
10390                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10391                         else
10392                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10393                 }
10394                 texture->currentframe = t;
10395         }
10396
10397         // update currentskinframe to be a qw skin or animation frame
10398         if (rsurface.ent_qwskin >= 0)
10399         {
10400                 i = rsurface.ent_qwskin;
10401                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10402                 {
10403                         r_qwskincache_size = cl.maxclients;
10404                         if (r_qwskincache)
10405                                 Mem_Free(r_qwskincache);
10406                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10407                 }
10408                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10409                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10410                 t->currentskinframe = r_qwskincache[i].skinframe;
10411                 if (t->currentskinframe == NULL)
10412                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10413         }
10414         else if (t->numskinframes >= 2)
10415                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10416         if (t->backgroundnumskinframes >= 2)
10417                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10418
10419         t->currentmaterialflags = t->basematerialflags;
10420         t->currentalpha = rsurface.colormod[3];
10421         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10422                 t->currentalpha *= r_wateralpha.value;
10423         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10424                 t->currentalpha *= t->r_water_wateralpha;
10425         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10426                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10427         if (!(rsurface.ent_flags & RENDER_LIGHT))
10428                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10429         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10430         {
10431                 // pick a model lighting mode
10432                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10433                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10434                 else
10435                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10436         }
10437         if (rsurface.ent_flags & RENDER_ADDITIVE)
10438                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10439         else if (t->currentalpha < 1)
10440                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10441         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10442                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10443         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10444                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10445         if (t->backgroundnumskinframes)
10446                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10447         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10448         {
10449                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10450                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10451         }
10452         else
10453                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10454         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10455                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10456
10457         // there is no tcmod
10458         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10459         {
10460                 t->currenttexmatrix = r_waterscrollmatrix;
10461                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10462         }
10463         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10464         {
10465                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10466                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10467         }
10468
10469         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10470                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10471         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10472                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10473
10474         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10475         if (t->currentskinframe->qpixels)
10476                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10477         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10478         if (!t->basetexture)
10479                 t->basetexture = r_texture_notexture;
10480         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10481         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10482         t->nmaptexture = t->currentskinframe->nmap;
10483         if (!t->nmaptexture)
10484                 t->nmaptexture = r_texture_blanknormalmap;
10485         t->glosstexture = r_texture_black;
10486         t->glowtexture = t->currentskinframe->glow;
10487         t->fogtexture = t->currentskinframe->fog;
10488         t->reflectmasktexture = t->currentskinframe->reflect;
10489         if (t->backgroundnumskinframes)
10490         {
10491                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10492                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10493                 t->backgroundglosstexture = r_texture_black;
10494                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10495                 if (!t->backgroundnmaptexture)
10496                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10497         }
10498         else
10499         {
10500                 t->backgroundbasetexture = r_texture_white;
10501                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10502                 t->backgroundglosstexture = r_texture_black;
10503                 t->backgroundglowtexture = NULL;
10504         }
10505         t->specularpower = r_shadow_glossexponent.value;
10506         // TODO: store reference values for these in the texture?
10507         t->specularscale = 0;
10508         if (r_shadow_gloss.integer > 0)
10509         {
10510                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10511                 {
10512                         if (r_shadow_glossintensity.value > 0)
10513                         {
10514                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10515                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10516                                 t->specularscale = r_shadow_glossintensity.value;
10517                         }
10518                 }
10519                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10520                 {
10521                         t->glosstexture = r_texture_white;
10522                         t->backgroundglosstexture = r_texture_white;
10523                         t->specularscale = r_shadow_gloss2intensity.value;
10524                         t->specularpower = r_shadow_gloss2exponent.value;
10525                 }
10526         }
10527         t->specularscale *= t->specularscalemod;
10528         t->specularpower *= t->specularpowermod;
10529
10530         // lightmaps mode looks bad with dlights using actual texturing, so turn
10531         // off the colormap and glossmap, but leave the normalmap on as it still
10532         // accurately represents the shading involved
10533         if (gl_lightmaps.integer)
10534         {
10535                 t->basetexture = r_texture_grey128;
10536                 t->pantstexture = r_texture_black;
10537                 t->shirttexture = r_texture_black;
10538                 t->nmaptexture = r_texture_blanknormalmap;
10539                 t->glosstexture = r_texture_black;
10540                 t->glowtexture = NULL;
10541                 t->fogtexture = NULL;
10542                 t->reflectmasktexture = NULL;
10543                 t->backgroundbasetexture = NULL;
10544                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10545                 t->backgroundglosstexture = r_texture_black;
10546                 t->backgroundglowtexture = NULL;
10547                 t->specularscale = 0;
10548                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10549         }
10550
10551         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10552         VectorClear(t->dlightcolor);
10553         t->currentnumlayers = 0;
10554         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10555         {
10556                 int blendfunc1, blendfunc2;
10557                 qboolean depthmask;
10558                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10559                 {
10560                         blendfunc1 = GL_SRC_ALPHA;
10561                         blendfunc2 = GL_ONE;
10562                 }
10563                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10564                 {
10565                         blendfunc1 = GL_SRC_ALPHA;
10566                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10567                 }
10568                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10569                 {
10570                         blendfunc1 = t->customblendfunc[0];
10571                         blendfunc2 = t->customblendfunc[1];
10572                 }
10573                 else
10574                 {
10575                         blendfunc1 = GL_ONE;
10576                         blendfunc2 = GL_ZERO;
10577                 }
10578                 // don't colormod evilblend textures
10579                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10580                         VectorSet(t->lightmapcolor, 1, 1, 1);
10581                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10582                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10583                 {
10584                         // fullbright is not affected by r_refdef.lightmapintensity
10585                         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]);
10586                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10587                                 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]);
10588                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10589                                 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]);
10590                 }
10591                 else
10592                 {
10593                         vec3_t ambientcolor;
10594                         float colorscale;
10595                         // set the color tint used for lights affecting this surface
10596                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10597                         colorscale = 2;
10598                         // q3bsp has no lightmap updates, so the lightstylevalue that
10599                         // would normally be baked into the lightmap must be
10600                         // applied to the color
10601                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10602                         if (model->type == mod_brushq3)
10603                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10604                         colorscale *= r_refdef.lightmapintensity;
10605                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10606                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10607                         // basic lit geometry
10608                         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]);
10609                         // add pants/shirt if needed
10610                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10611                                 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]);
10612                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10613                                 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]);
10614                         // now add ambient passes if needed
10615                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10616                         {
10617                                 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]);
10618                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10619                                         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]);
10620                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10621                                         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]);
10622                         }
10623                 }
10624                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10625                         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]);
10626                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10627                 {
10628                         // if this is opaque use alpha blend which will darken the earlier
10629                         // passes cheaply.
10630                         //
10631                         // if this is an alpha blended material, all the earlier passes
10632                         // were darkened by fog already, so we only need to add the fog
10633                         // color ontop through the fog mask texture
10634                         //
10635                         // if this is an additive blended material, all the earlier passes
10636                         // were darkened by fog already, and we should not add fog color
10637                         // (because the background was not darkened, there is no fog color
10638                         // that was lost behind it).
10639                         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]);
10640                 }
10641         }
10642
10643         return t->currentframe;
10644 }
10645
10646 rsurfacestate_t rsurface;
10647
10648 void R_Mesh_ResizeArrays(int newvertices)
10649 {
10650         unsigned char *base;
10651         size_t size;
10652         if (rsurface.array_size >= newvertices)
10653                 return;
10654         if (rsurface.array_base)
10655                 Mem_Free(rsurface.array_base);
10656         rsurface.array_size = (newvertices + 1023) & ~1023;
10657         size = 0;
10658         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10659         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10660         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10661         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10662         size += rsurface.array_size * sizeof(float[3]);
10663         size += rsurface.array_size * sizeof(float[3]);
10664         size += rsurface.array_size * sizeof(float[3]);
10665         size += rsurface.array_size * sizeof(float[3]);
10666         size += rsurface.array_size * sizeof(float[3]);
10667         size += rsurface.array_size * sizeof(float[3]);
10668         size += rsurface.array_size * sizeof(float[3]);
10669         size += rsurface.array_size * sizeof(float[3]);
10670         size += rsurface.array_size * sizeof(float[4]);
10671         size += rsurface.array_size * sizeof(float[2]);
10672         size += rsurface.array_size * sizeof(float[2]);
10673         size += rsurface.array_size * sizeof(float[4]);
10674         size += rsurface.array_size * sizeof(int[3]);
10675         size += rsurface.array_size * sizeof(unsigned short[3]);
10676         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10677         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10678         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10679         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10680         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10681         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10682         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10683         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10684         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10685         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10686         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10687         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10688         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10689         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10690         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10691         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10692         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10693         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10694         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10695 }
10696
10697 void RSurf_ActiveWorldEntity(void)
10698 {
10699         dp_model_t *model = r_refdef.scene.worldmodel;
10700         //if (rsurface.entity == r_refdef.scene.worldentity)
10701         //      return;
10702         rsurface.entity = r_refdef.scene.worldentity;
10703         rsurface.skeleton = NULL;
10704         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10705         rsurface.ent_skinnum = 0;
10706         rsurface.ent_qwskin = -1;
10707         rsurface.ent_shadertime = 0;
10708         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10709         if (rsurface.array_size < model->surfmesh.num_vertices)
10710                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10711         rsurface.matrix = identitymatrix;
10712         rsurface.inversematrix = identitymatrix;
10713         rsurface.matrixscale = 1;
10714         rsurface.inversematrixscale = 1;
10715         R_EntityMatrix(&identitymatrix);
10716         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10717         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10718         rsurface.fograngerecip = r_refdef.fograngerecip;
10719         rsurface.fogheightfade = r_refdef.fogheightfade;
10720         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10721         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10722         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10723         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10724         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10725         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10726         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10727         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10728         rsurface.colormod[3] = 1;
10729         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);
10730         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10731         rsurface.frameblend[0].lerp = 1;
10732         rsurface.ent_alttextures = false;
10733         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10734         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10735         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10736         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10737         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10738         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10739         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10740         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10741         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10742         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10743         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10744         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10745         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10746         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10747         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10748         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10749         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10750         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10751         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10752         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10753         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10754         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10755         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10756         rsurface.modelelement3i = model->surfmesh.data_element3i;
10757         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10758         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10759         rsurface.modelelement3s = model->surfmesh.data_element3s;
10760         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10761         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10762         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10763         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10764         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10765         rsurface.modelsurfaces = model->data_surfaces;
10766         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10767         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10768         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10769         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10770         rsurface.modelgeneratedvertex = false;
10771         rsurface.batchgeneratedvertex = false;
10772         rsurface.batchfirstvertex = 0;
10773         rsurface.batchnumvertices = 0;
10774         rsurface.batchfirsttriangle = 0;
10775         rsurface.batchnumtriangles = 0;
10776         rsurface.batchvertex3f  = NULL;
10777         rsurface.batchvertex3f_vertexbuffer = NULL;
10778         rsurface.batchvertex3f_bufferoffset = 0;
10779         rsurface.batchsvector3f = NULL;
10780         rsurface.batchsvector3f_vertexbuffer = NULL;
10781         rsurface.batchsvector3f_bufferoffset = 0;
10782         rsurface.batchtvector3f = NULL;
10783         rsurface.batchtvector3f_vertexbuffer = NULL;
10784         rsurface.batchtvector3f_bufferoffset = 0;
10785         rsurface.batchnormal3f  = NULL;
10786         rsurface.batchnormal3f_vertexbuffer = NULL;
10787         rsurface.batchnormal3f_bufferoffset = 0;
10788         rsurface.batchlightmapcolor4f = NULL;
10789         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10790         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10791         rsurface.batchtexcoordtexture2f = NULL;
10792         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10793         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10794         rsurface.batchtexcoordlightmap2f = NULL;
10795         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10796         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10797         rsurface.batchvertexmesh = NULL;
10798         rsurface.batchvertexmeshbuffer = NULL;
10799         rsurface.batchvertexposition = NULL;
10800         rsurface.batchvertexpositionbuffer = NULL;
10801         rsurface.batchelement3i = NULL;
10802         rsurface.batchelement3i_indexbuffer = NULL;
10803         rsurface.batchelement3i_bufferoffset = 0;
10804         rsurface.batchelement3s = NULL;
10805         rsurface.batchelement3s_indexbuffer = NULL;
10806         rsurface.batchelement3s_bufferoffset = 0;
10807         rsurface.passcolor4f = NULL;
10808         rsurface.passcolor4f_vertexbuffer = NULL;
10809         rsurface.passcolor4f_bufferoffset = 0;
10810 }
10811
10812 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10813 {
10814         dp_model_t *model = ent->model;
10815         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10816         //      return;
10817         rsurface.entity = (entity_render_t *)ent;
10818         rsurface.skeleton = ent->skeleton;
10819         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10820         rsurface.ent_skinnum = ent->skinnum;
10821         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;
10822         rsurface.ent_shadertime = ent->shadertime;
10823         rsurface.ent_flags = ent->flags;
10824         if (rsurface.array_size < model->surfmesh.num_vertices)
10825                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10826         rsurface.matrix = ent->matrix;
10827         rsurface.inversematrix = ent->inversematrix;
10828         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10829         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10830         R_EntityMatrix(&rsurface.matrix);
10831         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10832         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10833         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10834         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10835         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10836         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10837         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10838         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10839         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10840         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10841         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10842         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10843         rsurface.colormod[3] = ent->alpha;
10844         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10845         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10846         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10847         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10848         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10849         if (ent->model->brush.submodel && !prepass)
10850         {
10851                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10852                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10853         }
10854         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10855         {
10856                 if (ent->animcache_vertex3f && !r_framedata_failed)
10857                 {
10858                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10859                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10860                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10861                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10862                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10863                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10864                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10865                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10866                 }
10867                 else if (wanttangents)
10868                 {
10869                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10870                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10871                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10872                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10873                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10874                         rsurface.modelvertexmesh = NULL;
10875                         rsurface.modelvertexmeshbuffer = NULL;
10876                         rsurface.modelvertexposition = NULL;
10877                         rsurface.modelvertexpositionbuffer = NULL;
10878                 }
10879                 else if (wantnormals)
10880                 {
10881                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10882                         rsurface.modelsvector3f = NULL;
10883                         rsurface.modeltvector3f = NULL;
10884                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10885                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10886                         rsurface.modelvertexmesh = NULL;
10887                         rsurface.modelvertexmeshbuffer = NULL;
10888                         rsurface.modelvertexposition = NULL;
10889                         rsurface.modelvertexpositionbuffer = NULL;
10890                 }
10891                 else
10892                 {
10893                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10894                         rsurface.modelsvector3f = NULL;
10895                         rsurface.modeltvector3f = NULL;
10896                         rsurface.modelnormal3f = NULL;
10897                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10898                         rsurface.modelvertexmesh = NULL;
10899                         rsurface.modelvertexmeshbuffer = NULL;
10900                         rsurface.modelvertexposition = NULL;
10901                         rsurface.modelvertexpositionbuffer = NULL;
10902                 }
10903                 rsurface.modelvertex3f_vertexbuffer = 0;
10904                 rsurface.modelvertex3f_bufferoffset = 0;
10905                 rsurface.modelsvector3f_vertexbuffer = 0;
10906                 rsurface.modelsvector3f_bufferoffset = 0;
10907                 rsurface.modeltvector3f_vertexbuffer = 0;
10908                 rsurface.modeltvector3f_bufferoffset = 0;
10909                 rsurface.modelnormal3f_vertexbuffer = 0;
10910                 rsurface.modelnormal3f_bufferoffset = 0;
10911                 rsurface.modelgeneratedvertex = true;
10912         }
10913         else
10914         {
10915                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10916                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10917                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10918                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10919                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10920                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10921                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10922                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10923                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10924                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10925                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10926                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10927                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10928                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10929                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10930                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10931                 rsurface.modelgeneratedvertex = false;
10932         }
10933         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10934         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10935         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10936         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10937         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10938         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10939         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10940         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10941         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10942         rsurface.modelelement3i = model->surfmesh.data_element3i;
10943         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10944         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10945         rsurface.modelelement3s = model->surfmesh.data_element3s;
10946         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10947         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10948         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10949         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10950         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10951         rsurface.modelsurfaces = model->data_surfaces;
10952         rsurface.batchgeneratedvertex = false;
10953         rsurface.batchfirstvertex = 0;
10954         rsurface.batchnumvertices = 0;
10955         rsurface.batchfirsttriangle = 0;
10956         rsurface.batchnumtriangles = 0;
10957         rsurface.batchvertex3f  = NULL;
10958         rsurface.batchvertex3f_vertexbuffer = NULL;
10959         rsurface.batchvertex3f_bufferoffset = 0;
10960         rsurface.batchsvector3f = NULL;
10961         rsurface.batchsvector3f_vertexbuffer = NULL;
10962         rsurface.batchsvector3f_bufferoffset = 0;
10963         rsurface.batchtvector3f = NULL;
10964         rsurface.batchtvector3f_vertexbuffer = NULL;
10965         rsurface.batchtvector3f_bufferoffset = 0;
10966         rsurface.batchnormal3f  = NULL;
10967         rsurface.batchnormal3f_vertexbuffer = NULL;
10968         rsurface.batchnormal3f_bufferoffset = 0;
10969         rsurface.batchlightmapcolor4f = NULL;
10970         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10971         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10972         rsurface.batchtexcoordtexture2f = NULL;
10973         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10974         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10975         rsurface.batchtexcoordlightmap2f = NULL;
10976         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10977         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10978         rsurface.batchvertexmesh = NULL;
10979         rsurface.batchvertexmeshbuffer = NULL;
10980         rsurface.batchvertexposition = NULL;
10981         rsurface.batchvertexpositionbuffer = NULL;
10982         rsurface.batchelement3i = NULL;
10983         rsurface.batchelement3i_indexbuffer = NULL;
10984         rsurface.batchelement3i_bufferoffset = 0;
10985         rsurface.batchelement3s = NULL;
10986         rsurface.batchelement3s_indexbuffer = NULL;
10987         rsurface.batchelement3s_bufferoffset = 0;
10988         rsurface.passcolor4f = NULL;
10989         rsurface.passcolor4f_vertexbuffer = NULL;
10990         rsurface.passcolor4f_bufferoffset = 0;
10991 }
10992
10993 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)
10994 {
10995         int i;
10996
10997         rsurface.entity = r_refdef.scene.worldentity;
10998         rsurface.skeleton = NULL;
10999         rsurface.ent_skinnum = 0;
11000         rsurface.ent_qwskin = -1;
11001         rsurface.ent_shadertime = shadertime;
11002         rsurface.ent_flags = entflags;
11003         rsurface.modelnumvertices = numvertices;
11004         rsurface.modelnumtriangles = numtriangles;
11005         if (rsurface.array_size < rsurface.modelnumvertices)
11006                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11007         rsurface.matrix = *matrix;
11008         rsurface.inversematrix = *inversematrix;
11009         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11010         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11011         R_EntityMatrix(&rsurface.matrix);
11012         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11013         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11014         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11015         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11016         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11017         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11018         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11019         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11020         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11021         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11022         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11023         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11024         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);
11025         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11026         rsurface.frameblend[0].lerp = 1;
11027         rsurface.ent_alttextures = false;
11028         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11029         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11030         if (wanttangents)
11031         {
11032                 rsurface.modelvertex3f = vertex3f;
11033                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11034                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11035                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11036         }
11037         else if (wantnormals)
11038         {
11039                 rsurface.modelvertex3f = vertex3f;
11040                 rsurface.modelsvector3f = NULL;
11041                 rsurface.modeltvector3f = NULL;
11042                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11043         }
11044         else
11045         {
11046                 rsurface.modelvertex3f = vertex3f;
11047                 rsurface.modelsvector3f = NULL;
11048                 rsurface.modeltvector3f = NULL;
11049                 rsurface.modelnormal3f = NULL;
11050         }
11051         rsurface.modelvertexmesh = NULL;
11052         rsurface.modelvertexmeshbuffer = NULL;
11053         rsurface.modelvertexposition = NULL;
11054         rsurface.modelvertexpositionbuffer = NULL;
11055         rsurface.modelvertex3f_vertexbuffer = 0;
11056         rsurface.modelvertex3f_bufferoffset = 0;
11057         rsurface.modelsvector3f_vertexbuffer = 0;
11058         rsurface.modelsvector3f_bufferoffset = 0;
11059         rsurface.modeltvector3f_vertexbuffer = 0;
11060         rsurface.modeltvector3f_bufferoffset = 0;
11061         rsurface.modelnormal3f_vertexbuffer = 0;
11062         rsurface.modelnormal3f_bufferoffset = 0;
11063         rsurface.modelgeneratedvertex = true;
11064         rsurface.modellightmapcolor4f  = color4f;
11065         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11066         rsurface.modellightmapcolor4f_bufferoffset = 0;
11067         rsurface.modeltexcoordtexture2f  = texcoord2f;
11068         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11069         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11070         rsurface.modeltexcoordlightmap2f  = NULL;
11071         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11072         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11073         rsurface.modelelement3i = element3i;
11074         rsurface.modelelement3i_indexbuffer = NULL;
11075         rsurface.modelelement3i_bufferoffset = 0;
11076         rsurface.modelelement3s = element3s;
11077         rsurface.modelelement3s_indexbuffer = NULL;
11078         rsurface.modelelement3s_bufferoffset = 0;
11079         rsurface.modellightmapoffsets = NULL;
11080         rsurface.modelsurfaces = NULL;
11081         rsurface.batchgeneratedvertex = false;
11082         rsurface.batchfirstvertex = 0;
11083         rsurface.batchnumvertices = 0;
11084         rsurface.batchfirsttriangle = 0;
11085         rsurface.batchnumtriangles = 0;
11086         rsurface.batchvertex3f  = NULL;
11087         rsurface.batchvertex3f_vertexbuffer = NULL;
11088         rsurface.batchvertex3f_bufferoffset = 0;
11089         rsurface.batchsvector3f = NULL;
11090         rsurface.batchsvector3f_vertexbuffer = NULL;
11091         rsurface.batchsvector3f_bufferoffset = 0;
11092         rsurface.batchtvector3f = NULL;
11093         rsurface.batchtvector3f_vertexbuffer = NULL;
11094         rsurface.batchtvector3f_bufferoffset = 0;
11095         rsurface.batchnormal3f  = NULL;
11096         rsurface.batchnormal3f_vertexbuffer = NULL;
11097         rsurface.batchnormal3f_bufferoffset = 0;
11098         rsurface.batchlightmapcolor4f = NULL;
11099         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11100         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11101         rsurface.batchtexcoordtexture2f = NULL;
11102         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11103         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11104         rsurface.batchtexcoordlightmap2f = NULL;
11105         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11106         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11107         rsurface.batchvertexmesh = NULL;
11108         rsurface.batchvertexmeshbuffer = NULL;
11109         rsurface.batchvertexposition = NULL;
11110         rsurface.batchvertexpositionbuffer = NULL;
11111         rsurface.batchelement3i = NULL;
11112         rsurface.batchelement3i_indexbuffer = NULL;
11113         rsurface.batchelement3i_bufferoffset = 0;
11114         rsurface.batchelement3s = NULL;
11115         rsurface.batchelement3s_indexbuffer = NULL;
11116         rsurface.batchelement3s_bufferoffset = 0;
11117         rsurface.passcolor4f = NULL;
11118         rsurface.passcolor4f_vertexbuffer = NULL;
11119         rsurface.passcolor4f_bufferoffset = 0;
11120
11121         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11122         {
11123                 if ((wantnormals || wanttangents) && !normal3f)
11124                 {
11125                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11126                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11127                 }
11128                 if (wanttangents && !svector3f)
11129                 {
11130                         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);
11131                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11132                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11133                 }
11134         }
11135
11136         // now convert arrays into vertexmesh structs
11137         for (i = 0;i < numvertices;i++)
11138         {
11139                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11140                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11141                 if (rsurface.modelsvector3f)
11142                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11143                 if (rsurface.modeltvector3f)
11144                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11145                 if (rsurface.modelnormal3f)
11146                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11147                 if (rsurface.modellightmapcolor4f)
11148                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11149                 if (rsurface.modeltexcoordtexture2f)
11150                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11151                 if (rsurface.modeltexcoordlightmap2f)
11152                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11153         }
11154 }
11155
11156 float RSurf_FogPoint(const float *v)
11157 {
11158         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11159         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11160         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11161         float FogHeightFade = r_refdef.fogheightfade;
11162         float fogfrac;
11163         unsigned int fogmasktableindex;
11164         if (r_refdef.fogplaneviewabove)
11165                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11166         else
11167                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11168         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11169         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11170 }
11171
11172 float RSurf_FogVertex(const float *v)
11173 {
11174         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11175         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11176         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11177         float FogHeightFade = rsurface.fogheightfade;
11178         float fogfrac;
11179         unsigned int fogmasktableindex;
11180         if (r_refdef.fogplaneviewabove)
11181                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11182         else
11183                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11184         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11185         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11186 }
11187
11188 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11189 {
11190         int i;
11191         for (i = 0;i < numelements;i++)
11192                 outelement3i[i] = inelement3i[i] + adjust;
11193 }
11194
11195 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11196 extern cvar_t gl_vbo;
11197 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11198 {
11199         int deformindex;
11200         int firsttriangle;
11201         int numtriangles;
11202         int firstvertex;
11203         int endvertex;
11204         int numvertices;
11205         int surfacefirsttriangle;
11206         int surfacenumtriangles;
11207         int surfacefirstvertex;
11208         int surfaceendvertex;
11209         int surfacenumvertices;
11210         int surfaceadjustvertex;
11211         int needsupdate;
11212         int i, j;
11213         qboolean gaps;
11214         qboolean dynamicvertex;
11215         float amplitude;
11216         float animpos;
11217         float scale;
11218         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11219         float waveparms[4];
11220         q3shaderinfo_deform_t *deform;
11221         const msurface_t *surface, *firstsurface;
11222         r_vertexposition_t *vertexposition;
11223         r_vertexmesh_t *vertexmesh;
11224         if (!texturenumsurfaces)
11225                 return;
11226         // find vertex range of this surface batch
11227         gaps = false;
11228         firstsurface = texturesurfacelist[0];
11229         firsttriangle = firstsurface->num_firsttriangle;
11230         numtriangles = 0;
11231         firstvertex = endvertex = firstsurface->num_firstvertex;
11232         for (i = 0;i < texturenumsurfaces;i++)
11233         {
11234                 surface = texturesurfacelist[i];
11235                 if (surface != firstsurface + i)
11236                         gaps = true;
11237                 surfacefirstvertex = surface->num_firstvertex;
11238                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11239                 surfacenumtriangles = surface->num_triangles;
11240                 if (firstvertex > surfacefirstvertex)
11241                         firstvertex = surfacefirstvertex;
11242                 if (endvertex < surfaceendvertex)
11243                         endvertex = surfaceendvertex;
11244                 numtriangles += surfacenumtriangles;
11245         }
11246         if (!numtriangles)
11247                 return;
11248
11249         // we now know the vertex range used, and if there are any gaps in it
11250         rsurface.batchfirstvertex = firstvertex;
11251         rsurface.batchnumvertices = endvertex - firstvertex;
11252         rsurface.batchfirsttriangle = firsttriangle;
11253         rsurface.batchnumtriangles = numtriangles;
11254
11255         // this variable holds flags for which properties have been updated that
11256         // may require regenerating vertexmesh or vertexposition arrays...
11257         needsupdate = 0;
11258
11259         // check if any dynamic vertex processing must occur
11260         dynamicvertex = false;
11261
11262         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11263                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11264         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11265         {
11266                 switch (deform->deform)
11267                 {
11268                 default:
11269                 case Q3DEFORM_PROJECTIONSHADOW:
11270                 case Q3DEFORM_TEXT0:
11271                 case Q3DEFORM_TEXT1:
11272                 case Q3DEFORM_TEXT2:
11273                 case Q3DEFORM_TEXT3:
11274                 case Q3DEFORM_TEXT4:
11275                 case Q3DEFORM_TEXT5:
11276                 case Q3DEFORM_TEXT6:
11277                 case Q3DEFORM_TEXT7:
11278                 case Q3DEFORM_NONE:
11279                         break;
11280                 case Q3DEFORM_AUTOSPRITE:
11281                         dynamicvertex = true;
11282                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11283                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11284                         break;
11285                 case Q3DEFORM_AUTOSPRITE2:
11286                         dynamicvertex = true;
11287                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11288                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11289                         break;
11290                 case Q3DEFORM_NORMAL:
11291                         dynamicvertex = true;
11292                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11293                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11294                         break;
11295                 case Q3DEFORM_WAVE:
11296                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11297                                 break; // if wavefunc is a nop, ignore this transform
11298                         dynamicvertex = true;
11299                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11300                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11301                         break;
11302                 case Q3DEFORM_BULGE:
11303                         dynamicvertex = true;
11304                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11305                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11306                         break;
11307                 case Q3DEFORM_MOVE:
11308                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11309                                 break; // if wavefunc is a nop, ignore this transform
11310                         dynamicvertex = true;
11311                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11312                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11313                         break;
11314                 }
11315         }
11316         switch(rsurface.texture->tcgen.tcgen)
11317         {
11318         default:
11319         case Q3TCGEN_TEXTURE:
11320                 break;
11321         case Q3TCGEN_LIGHTMAP:
11322                 dynamicvertex = true;
11323                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11324                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11325                 break;
11326         case Q3TCGEN_VECTOR:
11327                 dynamicvertex = true;
11328                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11329                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11330                 break;
11331         case Q3TCGEN_ENVIRONMENT:
11332                 dynamicvertex = true;
11333                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11334                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11335                 break;
11336         }
11337         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11338         {
11339                 dynamicvertex = true;
11340                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11341                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11342         }
11343
11344         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11345         {
11346                 dynamicvertex = true;
11347                 batchneed |= BATCHNEED_NOGAPS;
11348                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11349         }
11350
11351         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11352         {
11353                 dynamicvertex = true;
11354                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11355                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11356         }
11357
11358         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11359         {
11360                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11361                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11362                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11363                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11364                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11365                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11366                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11367         }
11368
11369         // when the model data has no vertex buffer (dynamic mesh), we need to
11370         // eliminate gaps
11371         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
11372                 batchneed |= BATCHNEED_NOGAPS;
11373
11374         // if needsupdate, we have to do a dynamic vertex batch for sure
11375         if (needsupdate & batchneed)
11376                 dynamicvertex = true;
11377
11378         // see if we need to build vertexmesh from arrays
11379         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11380                 dynamicvertex = true;
11381
11382         // see if we need to build vertexposition from arrays
11383         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11384                 dynamicvertex = true;
11385
11386         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11387         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11388                 dynamicvertex = true;
11389
11390         // if there is a chance of animated vertex colors, it's a dynamic batch
11391         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11392                 dynamicvertex = true;
11393
11394         rsurface.batchvertex3f = rsurface.modelvertex3f;
11395         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11396         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11397         rsurface.batchsvector3f = rsurface.modelsvector3f;
11398         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11399         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11400         rsurface.batchtvector3f = rsurface.modeltvector3f;
11401         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11402         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11403         rsurface.batchnormal3f = rsurface.modelnormal3f;
11404         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11405         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11406         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11407         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11408         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11409         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11410         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11411         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11412         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11413         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11414         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11415         rsurface.batchvertexposition = rsurface.modelvertexposition;
11416         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11417         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11418         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11419         rsurface.batchelement3i = rsurface.modelelement3i;
11420         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11421         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11422         rsurface.batchelement3s = rsurface.modelelement3s;
11423         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11424         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11425
11426         // if any dynamic vertex processing has to occur in software, we copy the
11427         // entire surface list together before processing to rebase the vertices
11428         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11429         //
11430         // if any gaps exist and we do not have a static vertex buffer, we have to
11431         // copy the surface list together to avoid wasting upload bandwidth on the
11432         // vertices in the gaps.
11433         //
11434         // if gaps exist and we have a static vertex buffer, we still have to
11435         // combine the index buffer ranges into one dynamic index buffer.
11436         //
11437         // in all cases we end up with data that can be drawn in one call.
11438
11439         if (!dynamicvertex)
11440         {
11441                 // static vertex data, just set pointers...
11442                 rsurface.batchgeneratedvertex = false;
11443                 // if there are gaps, we want to build a combined index buffer,
11444                 // otherwise use the original static buffer with an appropriate offset
11445                 if (gaps)
11446                 {
11447                         firsttriangle = 0;
11448                         numtriangles = 0;
11449                         for (i = 0;i < texturenumsurfaces;i++)
11450                         {
11451                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11452                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11453                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11454                                 numtriangles += surfacenumtriangles;
11455                         }
11456                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11457                         rsurface.batchelement3i_indexbuffer = NULL;
11458                         rsurface.batchelement3i_bufferoffset = 0;
11459                         rsurface.batchelement3s = NULL;
11460                         rsurface.batchelement3s_indexbuffer = NULL;
11461                         rsurface.batchelement3s_bufferoffset = 0;
11462                         if (endvertex <= 65536)
11463                         {
11464                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11465                                 for (i = 0;i < numtriangles*3;i++)
11466                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11467                         }
11468                         rsurface.batchfirsttriangle = firsttriangle;
11469                         rsurface.batchnumtriangles = numtriangles;
11470                 }
11471                 return;
11472         }
11473
11474         // something needs software processing, do it for real...
11475         // we only directly handle interleaved array data in this case...
11476         rsurface.batchgeneratedvertex = true;
11477
11478         // now copy the vertex data into a combined array and make an index array
11479         // (this is what Quake3 does all the time)
11480         //if (gaps || rsurface.batchfirstvertex)
11481         {
11482                 rsurface.batchvertexposition = NULL;
11483                 rsurface.batchvertexpositionbuffer = NULL;
11484                 rsurface.batchvertexmesh = NULL;
11485                 rsurface.batchvertexmeshbuffer = NULL;
11486                 rsurface.batchvertex3f = NULL;
11487                 rsurface.batchvertex3f_vertexbuffer = NULL;
11488                 rsurface.batchvertex3f_bufferoffset = 0;
11489                 rsurface.batchsvector3f = NULL;
11490                 rsurface.batchsvector3f_vertexbuffer = NULL;
11491                 rsurface.batchsvector3f_bufferoffset = 0;
11492                 rsurface.batchtvector3f = NULL;
11493                 rsurface.batchtvector3f_vertexbuffer = NULL;
11494                 rsurface.batchtvector3f_bufferoffset = 0;
11495                 rsurface.batchnormal3f = NULL;
11496                 rsurface.batchnormal3f_vertexbuffer = NULL;
11497                 rsurface.batchnormal3f_bufferoffset = 0;
11498                 rsurface.batchlightmapcolor4f = NULL;
11499                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11500                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11501                 rsurface.batchtexcoordtexture2f = NULL;
11502                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11503                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11504                 rsurface.batchtexcoordlightmap2f = NULL;
11505                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11506                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11507                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11508                 rsurface.batchelement3i_indexbuffer = NULL;
11509                 rsurface.batchelement3i_bufferoffset = 0;
11510                 rsurface.batchelement3s = NULL;
11511                 rsurface.batchelement3s_indexbuffer = NULL;
11512                 rsurface.batchelement3s_bufferoffset = 0;
11513                 // we'll only be setting up certain arrays as needed
11514                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11515                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11516                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11517                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11518                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11519                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11520                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11521                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11522                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11523                 {
11524                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11525                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11526                 }
11527                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11528                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11529                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11530                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11531                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11532                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11533                 numvertices = 0;
11534                 numtriangles = 0;
11535                 for (i = 0;i < texturenumsurfaces;i++)
11536                 {
11537                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11538                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11539                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11540                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11541                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11542                         // copy only the data requested
11543                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11544                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11545                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11546                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11547                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11548                         {
11549                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11550                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11551                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11552                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11553                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11554                                 {
11555                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11556                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11557                                 }
11558                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11559                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11560                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11561                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11562                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11563                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11564                         }
11565                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11566                         numvertices += surfacenumvertices;
11567                         numtriangles += surfacenumtriangles;
11568                 }
11569
11570                 // generate a 16bit index array as well if possible
11571                 // (in general, dynamic batches fit)
11572                 if (numvertices <= 65536)
11573                 {
11574                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11575                         for (i = 0;i < numtriangles*3;i++)
11576                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11577                 }
11578
11579                 // since we've copied everything, the batch now starts at 0
11580                 rsurface.batchfirstvertex = 0;
11581                 rsurface.batchnumvertices = numvertices;
11582                 rsurface.batchfirsttriangle = 0;
11583                 rsurface.batchnumtriangles = numtriangles;
11584         }
11585
11586         // q1bsp surfaces rendered in vertex color mode have to have colors
11587         // calculated based on lightstyles
11588         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11589         {
11590                 // generate color arrays for the surfaces in this list
11591                 int c[4];
11592                 int scale;
11593                 int size3;
11594                 const int *offsets;
11595                 const unsigned char *lm;
11596                 numvertices = 0;
11597                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11598                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11599                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11600                 for (i = 0;i < texturenumsurfaces;i++)
11601                 {
11602                         surface = texturesurfacelist[i];
11603                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11604                         surfacenumvertices = surface->num_vertices;
11605                         if (surface->lightmapinfo->samples)
11606                         {
11607                                 for (j = 0;j < surfacenumvertices;j++)
11608                                 {
11609                                         lm = surface->lightmapinfo->samples + offsets[j];
11610                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11611                                         VectorScale(lm, scale, c);
11612                                         if (surface->lightmapinfo->styles[1] != 255)
11613                                         {
11614                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11615                                                 lm += size3;
11616                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11617                                                 VectorMA(c, scale, lm, c);
11618                                                 if (surface->lightmapinfo->styles[2] != 255)
11619                                                 {
11620                                                         lm += size3;
11621                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11622                                                         VectorMA(c, scale, lm, c);
11623                                                         if (surface->lightmapinfo->styles[3] != 255)
11624                                                         {
11625                                                                 lm += size3;
11626                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11627                                                                 VectorMA(c, scale, lm, c);
11628                                                         }
11629                                                 }
11630                                         }
11631                                         c[0] >>= 15;
11632                                         c[1] >>= 15;
11633                                         c[2] >>= 15;
11634                                         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);
11635                                         numvertices++;
11636                                 }
11637                         }
11638                         else
11639                         {
11640                                 for (j = 0;j < surfacenumvertices;j++)
11641                                 {
11642                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11643                                         numvertices++;
11644                                 }
11645                         }
11646                 }
11647         }
11648
11649         // if vertices are deformed (sprite flares and things in maps, possibly
11650         // water waves, bulges and other deformations), modify the copied vertices
11651         // in place
11652         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11653         {
11654                 switch (deform->deform)
11655                 {
11656                 default:
11657                 case Q3DEFORM_PROJECTIONSHADOW:
11658                 case Q3DEFORM_TEXT0:
11659                 case Q3DEFORM_TEXT1:
11660                 case Q3DEFORM_TEXT2:
11661                 case Q3DEFORM_TEXT3:
11662                 case Q3DEFORM_TEXT4:
11663                 case Q3DEFORM_TEXT5:
11664                 case Q3DEFORM_TEXT6:
11665                 case Q3DEFORM_TEXT7:
11666                 case Q3DEFORM_NONE:
11667                         break;
11668                 case Q3DEFORM_AUTOSPRITE:
11669                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11670                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11671                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11672                         VectorNormalize(newforward);
11673                         VectorNormalize(newright);
11674                         VectorNormalize(newup);
11675                         // a single autosprite surface can contain multiple sprites...
11676                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11677                         {
11678                                 VectorClear(center);
11679                                 for (i = 0;i < 4;i++)
11680                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11681                                 VectorScale(center, 0.25f, center);
11682                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11683                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11684                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11685                                 for (i = 0;i < 4;i++)
11686                                 {
11687                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11688                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11689                                 }
11690                         }
11691                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11692                         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);
11693                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11694                         rsurface.batchvertex3f_vertexbuffer = NULL;
11695                         rsurface.batchvertex3f_bufferoffset = 0;
11696                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11697                         rsurface.batchsvector3f_vertexbuffer = NULL;
11698                         rsurface.batchsvector3f_bufferoffset = 0;
11699                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11700                         rsurface.batchtvector3f_vertexbuffer = NULL;
11701                         rsurface.batchtvector3f_bufferoffset = 0;
11702                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11703                         rsurface.batchnormal3f_vertexbuffer = NULL;
11704                         rsurface.batchnormal3f_bufferoffset = 0;
11705                         break;
11706                 case Q3DEFORM_AUTOSPRITE2:
11707                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11708                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11709                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11710                         VectorNormalize(newforward);
11711                         VectorNormalize(newright);
11712                         VectorNormalize(newup);
11713                         {
11714                                 const float *v1, *v2;
11715                                 vec3_t start, end;
11716                                 float f, l;
11717                                 struct
11718                                 {
11719                                         float length2;
11720                                         const float *v1;
11721                                         const float *v2;
11722                                 }
11723                                 shortest[2];
11724                                 memset(shortest, 0, sizeof(shortest));
11725                                 // a single autosprite surface can contain multiple sprites...
11726                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11727                                 {
11728                                         VectorClear(center);
11729                                         for (i = 0;i < 4;i++)
11730                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11731                                         VectorScale(center, 0.25f, center);
11732                                         // find the two shortest edges, then use them to define the
11733                                         // axis vectors for rotating around the central axis
11734                                         for (i = 0;i < 6;i++)
11735                                         {
11736                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11737                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11738                                                 l = VectorDistance2(v1, v2);
11739                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11740                                                 if (v1[2] != v2[2])
11741                                                         l += (1.0f / 1024.0f);
11742                                                 if (shortest[0].length2 > l || i == 0)
11743                                                 {
11744                                                         shortest[1] = shortest[0];
11745                                                         shortest[0].length2 = l;
11746                                                         shortest[0].v1 = v1;
11747                                                         shortest[0].v2 = v2;
11748                                                 }
11749                                                 else if (shortest[1].length2 > l || i == 1)
11750                                                 {
11751                                                         shortest[1].length2 = l;
11752                                                         shortest[1].v1 = v1;
11753                                                         shortest[1].v2 = v2;
11754                                                 }
11755                                         }
11756                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11757                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11758                                         // this calculates the right vector from the shortest edge
11759                                         // and the up vector from the edge midpoints
11760                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11761                                         VectorNormalize(right);
11762                                         VectorSubtract(end, start, up);
11763                                         VectorNormalize(up);
11764                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11765                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11766                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11767                                         VectorNegate(forward, forward);
11768                                         VectorReflect(forward, 0, up, forward);
11769                                         VectorNormalize(forward);
11770                                         CrossProduct(up, forward, newright);
11771                                         VectorNormalize(newright);
11772                                         // rotate the quad around the up axis vector, this is made
11773                                         // especially easy by the fact we know the quad is flat,
11774                                         // so we only have to subtract the center position and
11775                                         // measure distance along the right vector, and then
11776                                         // multiply that by the newright vector and add back the
11777                                         // center position
11778                                         // we also need to subtract the old position to undo the
11779                                         // displacement from the center, which we do with a
11780                                         // DotProduct, the subtraction/addition of center is also
11781                                         // optimized into DotProducts here
11782                                         l = DotProduct(right, center);
11783                                         for (i = 0;i < 4;i++)
11784                                         {
11785                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11786                                                 f = DotProduct(right, v1) - l;
11787                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11788                                         }
11789                                 }
11790                         }
11791                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11792                         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);
11793                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11794                         rsurface.batchvertex3f_vertexbuffer = NULL;
11795                         rsurface.batchvertex3f_bufferoffset = 0;
11796                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11797                         rsurface.batchsvector3f_vertexbuffer = NULL;
11798                         rsurface.batchsvector3f_bufferoffset = 0;
11799                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11800                         rsurface.batchtvector3f_vertexbuffer = NULL;
11801                         rsurface.batchtvector3f_bufferoffset = 0;
11802                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11803                         rsurface.batchnormal3f_vertexbuffer = NULL;
11804                         rsurface.batchnormal3f_bufferoffset = 0;
11805                         break;
11806                 case Q3DEFORM_NORMAL:
11807                         // deform the normals to make reflections wavey
11808                         for (j = 0;j < rsurface.batchnumvertices;j++)
11809                         {
11810                                 float vertex[3];
11811                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11812                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11813                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11814                                 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]);
11815                                 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]);
11816                                 VectorNormalize(normal);
11817                         }
11818                         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);
11819                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11820                         rsurface.batchsvector3f_vertexbuffer = NULL;
11821                         rsurface.batchsvector3f_bufferoffset = 0;
11822                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11823                         rsurface.batchtvector3f_vertexbuffer = NULL;
11824                         rsurface.batchtvector3f_bufferoffset = 0;
11825                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11826                         rsurface.batchnormal3f_vertexbuffer = NULL;
11827                         rsurface.batchnormal3f_bufferoffset = 0;
11828                         break;
11829                 case Q3DEFORM_WAVE:
11830                         // deform vertex array to make wavey water and flags and such
11831                         waveparms[0] = deform->waveparms[0];
11832                         waveparms[1] = deform->waveparms[1];
11833                         waveparms[2] = deform->waveparms[2];
11834                         waveparms[3] = deform->waveparms[3];
11835                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11836                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11837                         // this is how a divisor of vertex influence on deformation
11838                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11839                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11840                         for (j = 0;j < rsurface.batchnumvertices;j++)
11841                         {
11842                                 // if the wavefunc depends on time, evaluate it per-vertex
11843                                 if (waveparms[3])
11844                                 {
11845                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11846                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11847                                 }
11848                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11849                         }
11850                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11851                         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);
11852                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11853                         rsurface.batchvertex3f_vertexbuffer = NULL;
11854                         rsurface.batchvertex3f_bufferoffset = 0;
11855                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11856                         rsurface.batchsvector3f_vertexbuffer = NULL;
11857                         rsurface.batchsvector3f_bufferoffset = 0;
11858                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11859                         rsurface.batchtvector3f_vertexbuffer = NULL;
11860                         rsurface.batchtvector3f_bufferoffset = 0;
11861                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11862                         rsurface.batchnormal3f_vertexbuffer = NULL;
11863                         rsurface.batchnormal3f_bufferoffset = 0;
11864                         break;
11865                 case Q3DEFORM_BULGE:
11866                         // deform vertex array to make the surface have moving bulges
11867                         for (j = 0;j < rsurface.batchnumvertices;j++)
11868                         {
11869                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11870                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11871                         }
11872                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11873                         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);
11874                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11875                         rsurface.batchvertex3f_vertexbuffer = NULL;
11876                         rsurface.batchvertex3f_bufferoffset = 0;
11877                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11878                         rsurface.batchsvector3f_vertexbuffer = NULL;
11879                         rsurface.batchsvector3f_bufferoffset = 0;
11880                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11881                         rsurface.batchtvector3f_vertexbuffer = NULL;
11882                         rsurface.batchtvector3f_bufferoffset = 0;
11883                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11884                         rsurface.batchnormal3f_vertexbuffer = NULL;
11885                         rsurface.batchnormal3f_bufferoffset = 0;
11886                         break;
11887                 case Q3DEFORM_MOVE:
11888                         // deform vertex array
11889                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11890                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11891                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11892                         VectorScale(deform->parms, scale, waveparms);
11893                         for (j = 0;j < rsurface.batchnumvertices;j++)
11894                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11895                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11896                         rsurface.batchvertex3f_vertexbuffer = NULL;
11897                         rsurface.batchvertex3f_bufferoffset = 0;
11898                         break;
11899                 }
11900         }
11901
11902         // generate texcoords based on the chosen texcoord source
11903         switch(rsurface.texture->tcgen.tcgen)
11904         {
11905         default:
11906         case Q3TCGEN_TEXTURE:
11907                 break;
11908         case Q3TCGEN_LIGHTMAP:
11909                 if (rsurface.batchtexcoordlightmap2f)
11910                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11911                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11912                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11913                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11914                 break;
11915         case Q3TCGEN_VECTOR:
11916                 for (j = 0;j < rsurface.batchnumvertices;j++)
11917                 {
11918                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11919                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11920                 }
11921                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11922                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11923                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11924                 break;
11925         case Q3TCGEN_ENVIRONMENT:
11926                 // make environment reflections using a spheremap
11927                 for (j = 0;j < rsurface.batchnumvertices;j++)
11928                 {
11929                         // identical to Q3A's method, but executed in worldspace so
11930                         // carried models can be shiny too
11931
11932                         float viewer[3], d, reflected[3], worldreflected[3];
11933
11934                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11935                         // VectorNormalize(viewer);
11936
11937                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11938
11939                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11940                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11941                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11942                         // note: this is proportinal to viewer, so we can normalize later
11943
11944                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11945                         VectorNormalize(worldreflected);
11946
11947                         // note: this sphere map only uses world x and z!
11948                         // so positive and negative y will LOOK THE SAME.
11949                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11950                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11951                 }
11952                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11953                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11954                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11955                 break;
11956         }
11957         // the only tcmod that needs software vertex processing is turbulent, so
11958         // check for it here and apply the changes if needed
11959         // and we only support that as the first one
11960         // (handling a mixture of turbulent and other tcmods would be problematic
11961         //  without punting it entirely to a software path)
11962         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11963         {
11964                 amplitude = rsurface.texture->tcmods[0].parms[1];
11965                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11966                 for (j = 0;j < rsurface.batchnumvertices;j++)
11967                 {
11968                         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);
11969                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11970                 }
11971                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11972                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11973                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11974         }
11975
11976         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11977         {
11978                 // convert the modified arrays to vertex structs
11979                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11980                 rsurface.batchvertexmeshbuffer = NULL;
11981                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11982                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11983                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11984                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11985                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11986                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11987                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11988                 {
11989                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11990                         {
11991                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11992                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11993                         }
11994                 }
11995                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11996                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11997                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11998                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11999                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12000                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12001                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12002                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12003                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12004         }
12005
12006         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12007         {
12008                 // convert the modified arrays to vertex structs
12009                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12010                 rsurface.batchvertexpositionbuffer = NULL;
12011                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12012                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12013                 else
12014                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12015                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12016         }
12017 }
12018
12019 void RSurf_DrawBatch(void)
12020 {
12021         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);
12022 }
12023
12024 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12025 {
12026         // pick the closest matching water plane
12027         int planeindex, vertexindex, bestplaneindex = -1;
12028         float d, bestd;
12029         vec3_t vert;
12030         const float *v;
12031         r_waterstate_waterplane_t *p;
12032         bestd = 0;
12033         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12034         {
12035                 if(p->camera_entity != rsurface.texture->camera_entity)
12036                         continue;
12037                 d = 0;
12038                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12039                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12040                 {
12041                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12042                         d += fabs(PlaneDiff(vert, &p->plane));
12043                 }
12044                 if (bestd > d || bestplaneindex < 0)
12045                 {
12046                         bestd = d;
12047                         bestplaneindex = planeindex;
12048                 }
12049         }
12050         return bestplaneindex;
12051 }
12052
12053 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12054 {
12055         int i;
12056         for (i = 0;i < rsurface.batchnumvertices;i++)
12057                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12058         rsurface.passcolor4f = rsurface.array_passcolor4f;
12059         rsurface.passcolor4f_vertexbuffer = 0;
12060         rsurface.passcolor4f_bufferoffset = 0;
12061 }
12062
12063 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12064 {
12065         int i;
12066         float f;
12067         const float *v;
12068         const float *c;
12069         float *c2;
12070         if (rsurface.passcolor4f)
12071         {
12072                 // generate color arrays
12073                 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)
12074                 {
12075                         f = RSurf_FogVertex(v);
12076                         c2[0] = c[0] * f;
12077                         c2[1] = c[1] * f;
12078                         c2[2] = c[2] * f;
12079                         c2[3] = c[3];
12080                 }
12081         }
12082         else
12083         {
12084                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12085                 {
12086                         f = RSurf_FogVertex(v);
12087                         c2[0] = f;
12088                         c2[1] = f;
12089                         c2[2] = f;
12090                         c2[3] = 1;
12091                 }
12092         }
12093         rsurface.passcolor4f = rsurface.array_passcolor4f;
12094         rsurface.passcolor4f_vertexbuffer = 0;
12095         rsurface.passcolor4f_bufferoffset = 0;
12096 }
12097
12098 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12099 {
12100         int i;
12101         float f;
12102         const float *v;
12103         const float *c;
12104         float *c2;
12105         if (!rsurface.passcolor4f)
12106                 return;
12107         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)
12108         {
12109                 f = RSurf_FogVertex(v);
12110                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12111                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12112                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12113                 c2[3] = c[3];
12114         }
12115         rsurface.passcolor4f = rsurface.array_passcolor4f;
12116         rsurface.passcolor4f_vertexbuffer = 0;
12117         rsurface.passcolor4f_bufferoffset = 0;
12118 }
12119
12120 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12121 {
12122         int i;
12123         const float *c;
12124         float *c2;
12125         if (!rsurface.passcolor4f)
12126                 return;
12127         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12128         {
12129                 c2[0] = c[0] * r;
12130                 c2[1] = c[1] * g;
12131                 c2[2] = c[2] * b;
12132                 c2[3] = c[3] * a;
12133         }
12134         rsurface.passcolor4f = rsurface.array_passcolor4f;
12135         rsurface.passcolor4f_vertexbuffer = 0;
12136         rsurface.passcolor4f_bufferoffset = 0;
12137 }
12138
12139 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12140 {
12141         int i;
12142         const float *c;
12143         float *c2;
12144         if (!rsurface.passcolor4f)
12145                 return;
12146         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12147         {
12148                 c2[0] = c[0] + r_refdef.scene.ambient;
12149                 c2[1] = c[1] + r_refdef.scene.ambient;
12150                 c2[2] = c[2] + r_refdef.scene.ambient;
12151                 c2[3] = c[3];
12152         }
12153         rsurface.passcolor4f = rsurface.array_passcolor4f;
12154         rsurface.passcolor4f_vertexbuffer = 0;
12155         rsurface.passcolor4f_bufferoffset = 0;
12156 }
12157
12158 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12159 {
12160         // TODO: optimize
12161         rsurface.passcolor4f = NULL;
12162         rsurface.passcolor4f_vertexbuffer = 0;
12163         rsurface.passcolor4f_bufferoffset = 0;
12164         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12165         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12166         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12167         GL_Color(r, g, b, a);
12168         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12169         RSurf_DrawBatch();
12170 }
12171
12172 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12173 {
12174         // TODO: optimize applyfog && applycolor case
12175         // just apply fog if necessary, and tint the fog color array if necessary
12176         rsurface.passcolor4f = NULL;
12177         rsurface.passcolor4f_vertexbuffer = 0;
12178         rsurface.passcolor4f_bufferoffset = 0;
12179         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12180         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12181         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12182         GL_Color(r, g, b, a);
12183         RSurf_DrawBatch();
12184 }
12185
12186 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12187 {
12188         // TODO: optimize
12189         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12190         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12191         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12192         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12193         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12194         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12195         GL_Color(r, g, b, a);
12196         RSurf_DrawBatch();
12197 }
12198
12199 static void RSurf_DrawBatch_GL11_ClampColor(void)
12200 {
12201         int i;
12202         const float *c1;
12203         float *c2;
12204         if (!rsurface.passcolor4f)
12205                 return;
12206         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12207         {
12208                 c2[0] = bound(0.0f, c1[0], 1.0f);
12209                 c2[1] = bound(0.0f, c1[1], 1.0f);
12210                 c2[2] = bound(0.0f, c1[2], 1.0f);
12211                 c2[3] = bound(0.0f, c1[3], 1.0f);
12212         }
12213 }
12214
12215 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12216 {
12217         int i;
12218         float f;
12219         float alpha;
12220         const float *v;
12221         const float *n;
12222         float *c;
12223         vec3_t ambientcolor;
12224         vec3_t diffusecolor;
12225         vec3_t lightdir;
12226         // TODO: optimize
12227         // model lighting
12228         VectorCopy(rsurface.modellight_lightdir, lightdir);
12229         f = 0.5f * r_refdef.lightmapintensity;
12230         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12231         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12232         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12233         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12234         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12235         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12236         alpha = *a;
12237         if (VectorLength2(diffusecolor) > 0)
12238         {
12239                 // q3-style directional shading
12240                 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)
12241                 {
12242                         if ((f = DotProduct(n, lightdir)) > 0)
12243                                 VectorMA(ambientcolor, f, diffusecolor, c);
12244                         else
12245                                 VectorCopy(ambientcolor, c);
12246                         c[3] = alpha;
12247                 }
12248                 *r = 1;
12249                 *g = 1;
12250                 *b = 1;
12251                 *a = 1;
12252                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12253                 rsurface.passcolor4f_vertexbuffer = 0;
12254                 rsurface.passcolor4f_bufferoffset = 0;
12255                 *applycolor = false;
12256         }
12257         else
12258         {
12259                 *r = ambientcolor[0];
12260                 *g = ambientcolor[1];
12261                 *b = ambientcolor[2];
12262                 rsurface.passcolor4f = NULL;
12263                 rsurface.passcolor4f_vertexbuffer = 0;
12264                 rsurface.passcolor4f_bufferoffset = 0;
12265         }
12266 }
12267
12268 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12269 {
12270         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12271         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12272         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12273         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12274         GL_Color(r, g, b, a);
12275         RSurf_DrawBatch();
12276 }
12277
12278 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12279 {
12280         int i;
12281         float f;
12282         const float *v;
12283         float *c;
12284         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12285         {
12286                 f = 1 - RSurf_FogVertex(v);
12287                 c[0] = r;
12288                 c[1] = g;
12289                 c[2] = b;
12290                 c[3] = f * a;
12291         }
12292 }
12293
12294 void RSurf_SetupDepthAndCulling(void)
12295 {
12296         // submodels are biased to avoid z-fighting with world surfaces that they
12297         // may be exactly overlapping (avoids z-fighting artifacts on certain
12298         // doors and things in Quake maps)
12299         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12300         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12301         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12302         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12303 }
12304
12305 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12306 {
12307         // transparent sky would be ridiculous
12308         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12309                 return;
12310         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12311         skyrenderlater = true;
12312         RSurf_SetupDepthAndCulling();
12313         GL_DepthMask(true);
12314         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12315         // skymasking on them, and Quake3 never did sky masking (unlike
12316         // software Quake and software Quake2), so disable the sky masking
12317         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12318         // and skymasking also looks very bad when noclipping outside the
12319         // level, so don't use it then either.
12320         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12321         {
12322                 R_Mesh_ResetTextureState();
12323                 if (skyrendermasked)
12324                 {
12325                         R_SetupShader_DepthOrShadow();
12326                         // depth-only (masking)
12327                         GL_ColorMask(0,0,0,0);
12328                         // just to make sure that braindead drivers don't draw
12329                         // anything despite that colormask...
12330                         GL_BlendFunc(GL_ZERO, GL_ONE);
12331                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12332                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12333                 }
12334                 else
12335                 {
12336                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12337                         // fog sky
12338                         GL_BlendFunc(GL_ONE, GL_ZERO);
12339                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12340                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12341                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12342                 }
12343                 RSurf_DrawBatch();
12344                 if (skyrendermasked)
12345                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12346         }
12347         R_Mesh_ResetTextureState();
12348         GL_Color(1, 1, 1, 1);
12349 }
12350
12351 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12352 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12353 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12354 {
12355         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12356                 return;
12357         if (prepass)
12358         {
12359                 // render screenspace normalmap to texture
12360                 GL_DepthMask(true);
12361                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12362                 RSurf_DrawBatch();
12363                 return;
12364         }
12365
12366         // bind lightmap texture
12367
12368         // water/refraction/reflection/camera surfaces have to be handled specially
12369         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12370         {
12371                 int start, end, startplaneindex;
12372                 for (start = 0;start < texturenumsurfaces;start = end)
12373                 {
12374                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12375                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12376                                 ;
12377                         // now that we have a batch using the same planeindex, render it
12378                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12379                         {
12380                                 // render water or distortion background
12381                                 GL_DepthMask(true);
12382                                 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));
12383                                 RSurf_DrawBatch();
12384                                 // blend surface on top
12385                                 GL_DepthMask(false);
12386                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12387                                 RSurf_DrawBatch();
12388                         }
12389                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12390                         {
12391                                 // render surface with reflection texture as input
12392                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12393                                 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));
12394                                 RSurf_DrawBatch();
12395                         }
12396                 }
12397                 return;
12398         }
12399
12400         // render surface batch normally
12401         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12402         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12403         RSurf_DrawBatch();
12404 }
12405
12406 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12407 {
12408         // OpenGL 1.3 path - anything not completely ancient
12409         qboolean applycolor;
12410         qboolean applyfog;
12411         int layerindex;
12412         const texturelayer_t *layer;
12413         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);
12414         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12415
12416         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12417         {
12418                 vec4_t layercolor;
12419                 int layertexrgbscale;
12420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12421                 {
12422                         if (layerindex == 0)
12423                                 GL_AlphaTest(true);
12424                         else
12425                         {
12426                                 GL_AlphaTest(false);
12427                                 GL_DepthFunc(GL_EQUAL);
12428                         }
12429                 }
12430                 GL_DepthMask(layer->depthmask && writedepth);
12431                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12432                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12433                 {
12434                         layertexrgbscale = 4;
12435                         VectorScale(layer->color, 0.25f, layercolor);
12436                 }
12437                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12438                 {
12439                         layertexrgbscale = 2;
12440                         VectorScale(layer->color, 0.5f, layercolor);
12441                 }
12442                 else
12443                 {
12444                         layertexrgbscale = 1;
12445                         VectorScale(layer->color, 1.0f, layercolor);
12446                 }
12447                 layercolor[3] = layer->color[3];
12448                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12449                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12450                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12451                 switch (layer->type)
12452                 {
12453                 case TEXTURELAYERTYPE_LITTEXTURE:
12454                         // single-pass lightmapped texture with 2x rgbscale
12455                         R_Mesh_TexBind(0, r_texture_white);
12456                         R_Mesh_TexMatrix(0, NULL);
12457                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12458                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12459                         R_Mesh_TexBind(1, layer->texture);
12460                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12461                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12462                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12463                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12464                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12465                         else if (rsurface.uselightmaptexture)
12466                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12467                         else
12468                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12469                         break;
12470                 case TEXTURELAYERTYPE_TEXTURE:
12471                         // singletexture unlit texture with transparency support
12472                         R_Mesh_TexBind(0, layer->texture);
12473                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12474                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12475                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12476                         R_Mesh_TexBind(1, 0);
12477                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12478                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12479                         break;
12480                 case TEXTURELAYERTYPE_FOG:
12481                         // singletexture fogging
12482                         if (layer->texture)
12483                         {
12484                                 R_Mesh_TexBind(0, layer->texture);
12485                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12486                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12487                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12488                         }
12489                         else
12490                         {
12491                                 R_Mesh_TexBind(0, 0);
12492                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12493                         }
12494                         R_Mesh_TexBind(1, 0);
12495                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12496                         // generate a color array for the fog pass
12497                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12498                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12499                         RSurf_DrawBatch();
12500                         break;
12501                 default:
12502                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12503                 }
12504         }
12505         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12506         {
12507                 GL_DepthFunc(GL_LEQUAL);
12508                 GL_AlphaTest(false);
12509         }
12510 }
12511
12512 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12513 {
12514         // OpenGL 1.1 - crusty old voodoo path
12515         qboolean applyfog;
12516         int layerindex;
12517         const texturelayer_t *layer;
12518         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);
12519         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12520
12521         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12522         {
12523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12524                 {
12525                         if (layerindex == 0)
12526                                 GL_AlphaTest(true);
12527                         else
12528                         {
12529                                 GL_AlphaTest(false);
12530                                 GL_DepthFunc(GL_EQUAL);
12531                         }
12532                 }
12533                 GL_DepthMask(layer->depthmask && writedepth);
12534                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12535                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12536                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12537                 switch (layer->type)
12538                 {
12539                 case TEXTURELAYERTYPE_LITTEXTURE:
12540                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12541                         {
12542                                 // two-pass lit texture with 2x rgbscale
12543                                 // first the lightmap pass
12544                                 R_Mesh_TexBind(0, r_texture_white);
12545                                 R_Mesh_TexMatrix(0, NULL);
12546                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12547                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12548                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12549                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12550                                 else if (rsurface.uselightmaptexture)
12551                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12552                                 else
12553                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12554                                 // then apply the texture to it
12555                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12556                                 R_Mesh_TexBind(0, layer->texture);
12557                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12558                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12559                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12560                                 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);
12561                         }
12562                         else
12563                         {
12564                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12565                                 R_Mesh_TexBind(0, layer->texture);
12566                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12567                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12568                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12569                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12570                                         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);
12571                                 else
12572                                         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);
12573                         }
12574                         break;
12575                 case TEXTURELAYERTYPE_TEXTURE:
12576                         // singletexture unlit texture with transparency support
12577                         R_Mesh_TexBind(0, layer->texture);
12578                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12579                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12580                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12581                         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);
12582                         break;
12583                 case TEXTURELAYERTYPE_FOG:
12584                         // singletexture fogging
12585                         if (layer->texture)
12586                         {
12587                                 R_Mesh_TexBind(0, layer->texture);
12588                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12589                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12590                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12591                         }
12592                         else
12593                         {
12594                                 R_Mesh_TexBind(0, 0);
12595                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12596                         }
12597                         // generate a color array for the fog pass
12598                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12599                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12600                         RSurf_DrawBatch();
12601                         break;
12602                 default:
12603                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12604                 }
12605         }
12606         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12607         {
12608                 GL_DepthFunc(GL_LEQUAL);
12609                 GL_AlphaTest(false);
12610         }
12611 }
12612
12613 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12614 {
12615         int vi;
12616         int j;
12617         r_vertexgeneric_t *batchvertex;
12618         float c[4];
12619
12620         GL_AlphaTest(false);
12621         R_Mesh_ResetTextureState();
12622         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12623
12624         if(rsurface.texture && rsurface.texture->currentskinframe)
12625         {
12626                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12627                 c[3] *= rsurface.texture->currentalpha;
12628         }
12629         else
12630         {
12631                 c[0] = 1;
12632                 c[1] = 0;
12633                 c[2] = 1;
12634                 c[3] = 1;
12635         }
12636
12637         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12638         {
12639                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12640                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12641                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12642         }
12643
12644         // brighten it up (as texture value 127 means "unlit")
12645         c[0] *= 2 * r_refdef.view.colorscale;
12646         c[1] *= 2 * r_refdef.view.colorscale;
12647         c[2] *= 2 * r_refdef.view.colorscale;
12648
12649         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12650                 c[3] *= r_wateralpha.value;
12651
12652         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12653         {
12654                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12655                 GL_DepthMask(false);
12656         }
12657         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12658         {
12659                 GL_BlendFunc(GL_ONE, GL_ONE);
12660                 GL_DepthMask(false);
12661         }
12662         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12663         {
12664                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12665                 GL_DepthMask(false);
12666         }
12667         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12668         {
12669                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12670                 GL_DepthMask(false);
12671         }
12672         else
12673         {
12674                 GL_BlendFunc(GL_ONE, GL_ZERO);
12675                 GL_DepthMask(writedepth);
12676         }
12677
12678         if (r_showsurfaces.integer == 3)
12679         {
12680                 rsurface.passcolor4f = NULL;
12681
12682                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12683                 {
12684                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12685
12686                         rsurface.passcolor4f = NULL;
12687                         rsurface.passcolor4f_vertexbuffer = 0;
12688                         rsurface.passcolor4f_bufferoffset = 0;
12689                 }
12690                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12691                 {
12692                         qboolean applycolor = true;
12693                         float one = 1.0;
12694
12695                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12696
12697                         r_refdef.lightmapintensity = 1;
12698                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12699                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12700                 }
12701                 else
12702                 {
12703                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12704
12705                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12706                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12707                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12708                 }
12709
12710                 if(!rsurface.passcolor4f)
12711                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12712
12713                 RSurf_DrawBatch_GL11_ApplyAmbient();
12714                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12715                 if(r_refdef.fogenabled)
12716                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12717                 RSurf_DrawBatch_GL11_ClampColor();
12718
12719                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12720                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12721                 RSurf_DrawBatch();
12722         }
12723         else if (!r_refdef.view.showdebug)
12724         {
12725                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12726                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12727                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12728                 {
12729                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12730                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12731                 }
12732                 R_Mesh_PrepareVertices_Generic_Unlock();
12733                 RSurf_DrawBatch();
12734         }
12735         else if (r_showsurfaces.integer == 4)
12736         {
12737                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12738                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12739                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12740                 {
12741                         unsigned char c = vi << 3;
12742                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12743                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12744                 }
12745                 R_Mesh_PrepareVertices_Generic_Unlock();
12746                 RSurf_DrawBatch();
12747         }
12748         else if (r_showsurfaces.integer == 2)
12749         {
12750                 const int *e;
12751                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12752                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12753                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12754                 {
12755                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12756                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12757                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12758                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12759                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12760                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12761                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12762                 }
12763                 R_Mesh_PrepareVertices_Generic_Unlock();
12764                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12765         }
12766         else
12767         {
12768                 int texturesurfaceindex;
12769                 int k;
12770                 const msurface_t *surface;
12771                 unsigned char surfacecolor4ub[4];
12772                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12773                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12774                 vi = 0;
12775                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12776                 {
12777                         surface = texturesurfacelist[texturesurfaceindex];
12778                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12779                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12780                         for (j = 0;j < surface->num_vertices;j++)
12781                         {
12782                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12783                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12784                                 vi++;
12785                         }
12786                 }
12787                 R_Mesh_PrepareVertices_Generic_Unlock();
12788                 RSurf_DrawBatch();
12789         }
12790 }
12791
12792 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12793 {
12794         CHECKGLERROR
12795         RSurf_SetupDepthAndCulling();
12796         if (r_showsurfaces.integer)
12797         {
12798                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12799                 return;
12800         }
12801         switch (vid.renderpath)
12802         {
12803         case RENDERPATH_GL20:
12804         case RENDERPATH_CGGL:
12805         case RENDERPATH_D3D9:
12806         case RENDERPATH_D3D10:
12807         case RENDERPATH_D3D11:
12808                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12809                 break;
12810         case RENDERPATH_GL13:
12811                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12812                 break;
12813         case RENDERPATH_GL11:
12814                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12815                 break;
12816         }
12817         CHECKGLERROR
12818 }
12819
12820 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12821 {
12822         CHECKGLERROR
12823         RSurf_SetupDepthAndCulling();
12824         if (r_showsurfaces.integer)
12825         {
12826                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12827                 return;
12828         }
12829         switch (vid.renderpath)
12830         {
12831         case RENDERPATH_GL20:
12832         case RENDERPATH_CGGL:
12833         case RENDERPATH_D3D9:
12834         case RENDERPATH_D3D10:
12835         case RENDERPATH_D3D11:
12836                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12837                 break;
12838         case RENDERPATH_GL13:
12839                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12840                 break;
12841         case RENDERPATH_GL11:
12842                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12843                 break;
12844         }
12845         CHECKGLERROR
12846 }
12847
12848 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12849 {
12850         int i, j;
12851         int texturenumsurfaces, endsurface;
12852         texture_t *texture;
12853         const msurface_t *surface;
12854 #define MAXBATCH_TRANSPARENTSURFACES 256
12855         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12856
12857         // if the model is static it doesn't matter what value we give for
12858         // wantnormals and wanttangents, so this logic uses only rules applicable
12859         // to a model, knowing that they are meaningless otherwise
12860         if (ent == r_refdef.scene.worldentity)
12861                 RSurf_ActiveWorldEntity();
12862         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12863                 RSurf_ActiveModelEntity(ent, false, false, false);
12864         else
12865         {
12866                 switch (vid.renderpath)
12867                 {
12868                 case RENDERPATH_GL20:
12869                 case RENDERPATH_CGGL:
12870                 case RENDERPATH_D3D9:
12871                 case RENDERPATH_D3D10:
12872                 case RENDERPATH_D3D11:
12873                         RSurf_ActiveModelEntity(ent, true, true, false);
12874                         break;
12875                 case RENDERPATH_GL13:
12876                 case RENDERPATH_GL11:
12877                         RSurf_ActiveModelEntity(ent, true, false, false);
12878                         break;
12879                 }
12880         }
12881
12882         if (r_transparentdepthmasking.integer)
12883         {
12884                 qboolean setup = false;
12885                 for (i = 0;i < numsurfaces;i = j)
12886                 {
12887                         j = i + 1;
12888                         surface = rsurface.modelsurfaces + surfacelist[i];
12889                         texture = surface->texture;
12890                         rsurface.texture = R_GetCurrentTexture(texture);
12891                         rsurface.lightmaptexture = NULL;
12892                         rsurface.deluxemaptexture = NULL;
12893                         rsurface.uselightmaptexture = false;
12894                         // scan ahead until we find a different texture
12895                         endsurface = min(i + 1024, numsurfaces);
12896                         texturenumsurfaces = 0;
12897                         texturesurfacelist[texturenumsurfaces++] = surface;
12898                         for (;j < endsurface;j++)
12899                         {
12900                                 surface = rsurface.modelsurfaces + surfacelist[j];
12901                                 if (texture != surface->texture)
12902                                         break;
12903                                 texturesurfacelist[texturenumsurfaces++] = surface;
12904                         }
12905                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12906                                 continue;
12907                         // render the range of surfaces as depth
12908                         if (!setup)
12909                         {
12910                                 setup = true;
12911                                 GL_ColorMask(0,0,0,0);
12912                                 GL_Color(1,1,1,1);
12913                                 GL_DepthTest(true);
12914                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12915                                 GL_DepthMask(true);
12916                                 GL_AlphaTest(false);
12917                                 R_Mesh_ResetTextureState();
12918                                 R_SetupShader_DepthOrShadow();
12919                         }
12920                         RSurf_SetupDepthAndCulling();
12921                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12922                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12923                         RSurf_DrawBatch();
12924                 }
12925                 if (setup)
12926                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12927         }
12928
12929         for (i = 0;i < numsurfaces;i = j)
12930         {
12931                 j = i + 1;
12932                 surface = rsurface.modelsurfaces + surfacelist[i];
12933                 texture = surface->texture;
12934                 rsurface.texture = R_GetCurrentTexture(texture);
12935                 rsurface.lightmaptexture = surface->lightmaptexture;
12936                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12937                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12938                 // scan ahead until we find a different texture
12939                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12940                 texturenumsurfaces = 0;
12941                 texturesurfacelist[texturenumsurfaces++] = surface;
12942                 for (;j < endsurface;j++)
12943                 {
12944                         surface = rsurface.modelsurfaces + surfacelist[j];
12945                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12946                                 break;
12947                         texturesurfacelist[texturenumsurfaces++] = surface;
12948                 }
12949                 // render the range of surfaces
12950                 if (ent == r_refdef.scene.worldentity)
12951                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12952                 else
12953                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12954         }
12955         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12956         GL_AlphaTest(false);
12957 }
12958
12959 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12960 {
12961         // transparent surfaces get pushed off into the transparent queue
12962         int surfacelistindex;
12963         const msurface_t *surface;
12964         vec3_t tempcenter, center;
12965         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12966         {
12967                 surface = texturesurfacelist[surfacelistindex];
12968                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12969                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12970                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12971                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12972                 if (queueentity->transparent_offset) // transparent offset
12973                 {
12974                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12975                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12976                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12977                 }
12978                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12979         }
12980 }
12981
12982 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12983 {
12984         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12985                 return;
12986         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12987                 return;
12988         RSurf_SetupDepthAndCulling();
12989         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12990         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12991         RSurf_DrawBatch();
12992 }
12993
12994 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12995 {
12996         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12997         CHECKGLERROR
12998         if (depthonly)
12999                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13000         else if (prepass)
13001         {
13002                 if (!rsurface.texture->currentnumlayers)
13003                         return;
13004                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13005                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13006                 else
13007                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13008         }
13009         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13010                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13011         else if (!rsurface.texture->currentnumlayers)
13012                 return;
13013         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13014         {
13015                 // in the deferred case, transparent surfaces were queued during prepass
13016                 if (!r_shadow_usingdeferredprepass)
13017                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13018         }
13019         else
13020         {
13021                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13022                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13023         }
13024         CHECKGLERROR
13025 }
13026
13027 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13028 {
13029         int i, j;
13030         texture_t *texture;
13031         // break the surface list down into batches by texture and use of lightmapping
13032         for (i = 0;i < numsurfaces;i = j)
13033         {
13034                 j = i + 1;
13035                 // texture is the base texture pointer, rsurface.texture is the
13036                 // current frame/skin the texture is directing us to use (for example
13037                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13038                 // use skin 1 instead)
13039                 texture = surfacelist[i]->texture;
13040                 rsurface.texture = R_GetCurrentTexture(texture);
13041                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13042                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13043                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13044                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13045                 {
13046                         // if this texture is not the kind we want, skip ahead to the next one
13047                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13048                                 ;
13049                         continue;
13050                 }
13051                 // simply scan ahead until we find a different texture or lightmap state
13052                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13053                         ;
13054                 // render the range of surfaces
13055                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13056         }
13057 }
13058
13059 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13060 {
13061         CHECKGLERROR
13062         if (depthonly)
13063                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13064         else if (prepass)
13065         {
13066                 if (!rsurface.texture->currentnumlayers)
13067                         return;
13068                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13069                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13070                 else
13071                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13072         }
13073         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13074                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13075         else if (!rsurface.texture->currentnumlayers)
13076                 return;
13077         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13078         {
13079                 // in the deferred case, transparent surfaces were queued during prepass
13080                 if (!r_shadow_usingdeferredprepass)
13081                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13082         }
13083         else
13084         {
13085                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13086                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13087         }
13088         CHECKGLERROR
13089 }
13090
13091 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13092 {
13093         int i, j;
13094         texture_t *texture;
13095         // break the surface list down into batches by texture and use of lightmapping
13096         for (i = 0;i < numsurfaces;i = j)
13097         {
13098                 j = i + 1;
13099                 // texture is the base texture pointer, rsurface.texture is the
13100                 // current frame/skin the texture is directing us to use (for example
13101                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13102                 // use skin 1 instead)
13103                 texture = surfacelist[i]->texture;
13104                 rsurface.texture = R_GetCurrentTexture(texture);
13105                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13106                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13107                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13108                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13109                 {
13110                         // if this texture is not the kind we want, skip ahead to the next one
13111                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13112                                 ;
13113                         continue;
13114                 }
13115                 // simply scan ahead until we find a different texture or lightmap state
13116                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13117                         ;
13118                 // render the range of surfaces
13119                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13120         }
13121 }
13122
13123 float locboxvertex3f[6*4*3] =
13124 {
13125         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13126         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13127         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13128         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13129         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13130         1,0,0, 0,0,0, 0,1,0, 1,1,0
13131 };
13132
13133 unsigned short locboxelements[6*2*3] =
13134 {
13135          0, 1, 2, 0, 2, 3,
13136          4, 5, 6, 4, 6, 7,
13137          8, 9,10, 8,10,11,
13138         12,13,14, 12,14,15,
13139         16,17,18, 16,18,19,
13140         20,21,22, 20,22,23
13141 };
13142
13143 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13144 {
13145         int i, j;
13146         cl_locnode_t *loc = (cl_locnode_t *)ent;
13147         vec3_t mins, size;
13148         float vertex3f[6*4*3];
13149         CHECKGLERROR
13150         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13151         GL_DepthMask(false);
13152         GL_DepthRange(0, 1);
13153         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13154         GL_DepthTest(true);
13155         GL_CullFace(GL_NONE);
13156         R_EntityMatrix(&identitymatrix);
13157
13158         R_Mesh_ResetTextureState();
13159
13160         i = surfacelist[0];
13161         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13162                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13163                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13164                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13165
13166         if (VectorCompare(loc->mins, loc->maxs))
13167         {
13168                 VectorSet(size, 2, 2, 2);
13169                 VectorMA(loc->mins, -0.5f, size, mins);
13170         }
13171         else
13172         {
13173                 VectorCopy(loc->mins, mins);
13174                 VectorSubtract(loc->maxs, loc->mins, size);
13175         }
13176
13177         for (i = 0;i < 6*4*3;)
13178                 for (j = 0;j < 3;j++, i++)
13179                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13180
13181         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13182         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13183         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13184 }
13185
13186 void R_DrawLocs(void)
13187 {
13188         int index;
13189         cl_locnode_t *loc, *nearestloc;
13190         vec3_t center;
13191         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13192         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13193         {
13194                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13195                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13196         }
13197 }
13198
13199 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13200 {
13201         if (decalsystem->decals)
13202                 Mem_Free(decalsystem->decals);
13203         memset(decalsystem, 0, sizeof(*decalsystem));
13204 }
13205
13206 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)
13207 {
13208         tridecal_t *decal;
13209         tridecal_t *decals;
13210         int i;
13211
13212         // expand or initialize the system
13213         if (decalsystem->maxdecals <= decalsystem->numdecals)
13214         {
13215                 decalsystem_t old = *decalsystem;
13216                 qboolean useshortelements;
13217                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13218                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13219                 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)));
13220                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13221                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13222                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13223                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13224                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13225                 if (decalsystem->numdecals)
13226                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13227                 if (old.decals)
13228                         Mem_Free(old.decals);
13229                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13230                         decalsystem->element3i[i] = i;
13231                 if (useshortelements)
13232                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13233                                 decalsystem->element3s[i] = i;
13234         }
13235
13236         // grab a decal and search for another free slot for the next one
13237         decals = decalsystem->decals;
13238         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13239         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13240                 ;
13241         decalsystem->freedecal = i;
13242         if (decalsystem->numdecals <= i)
13243                 decalsystem->numdecals = i + 1;
13244
13245         // initialize the decal
13246         decal->lived = 0;
13247         decal->triangleindex = triangleindex;
13248         decal->surfaceindex = surfaceindex;
13249         decal->decalsequence = decalsequence;
13250         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13251         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13252         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13253         decal->color4ub[0][3] = 255;
13254         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13255         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13256         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13257         decal->color4ub[1][3] = 255;
13258         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13259         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13260         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13261         decal->color4ub[2][3] = 255;
13262         decal->vertex3f[0][0] = v0[0];
13263         decal->vertex3f[0][1] = v0[1];
13264         decal->vertex3f[0][2] = v0[2];
13265         decal->vertex3f[1][0] = v1[0];
13266         decal->vertex3f[1][1] = v1[1];
13267         decal->vertex3f[1][2] = v1[2];
13268         decal->vertex3f[2][0] = v2[0];
13269         decal->vertex3f[2][1] = v2[1];
13270         decal->vertex3f[2][2] = v2[2];
13271         decal->texcoord2f[0][0] = t0[0];
13272         decal->texcoord2f[0][1] = t0[1];
13273         decal->texcoord2f[1][0] = t1[0];
13274         decal->texcoord2f[1][1] = t1[1];
13275         decal->texcoord2f[2][0] = t2[0];
13276         decal->texcoord2f[2][1] = t2[1];
13277 }
13278
13279 extern cvar_t cl_decals_bias;
13280 extern cvar_t cl_decals_models;
13281 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13282 // baseparms, parms, temps
13283 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)
13284 {
13285         int cornerindex;
13286         int index;
13287         float v[9][3];
13288         const float *vertex3f;
13289         int numpoints;
13290         float points[2][9][3];
13291         float temp[3];
13292         float tc[9][2];
13293         float f;
13294         float c[9][4];
13295         const int *e;
13296
13297         e = rsurface.modelelement3i + 3*triangleindex;
13298
13299         vertex3f = rsurface.modelvertex3f;
13300
13301         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13302         {
13303                 index = 3*e[cornerindex];
13304                 VectorCopy(vertex3f + index, v[cornerindex]);
13305         }
13306         // cull backfaces
13307         //TriangleNormal(v[0], v[1], v[2], normal);
13308         //if (DotProduct(normal, localnormal) < 0.0f)
13309         //      continue;
13310         // clip by each of the box planes formed from the projection matrix
13311         // if anything survives, we emit the decal
13312         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]);
13313         if (numpoints < 3)
13314                 return;
13315         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]);
13316         if (numpoints < 3)
13317                 return;
13318         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]);
13319         if (numpoints < 3)
13320                 return;
13321         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]);
13322         if (numpoints < 3)
13323                 return;
13324         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]);
13325         if (numpoints < 3)
13326                 return;
13327         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]);
13328         if (numpoints < 3)
13329                 return;
13330         // some part of the triangle survived, so we have to accept it...
13331         if (dynamic)
13332         {
13333                 // dynamic always uses the original triangle
13334                 numpoints = 3;
13335                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13336                 {
13337                         index = 3*e[cornerindex];
13338                         VectorCopy(vertex3f + index, v[cornerindex]);
13339                 }
13340         }
13341         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13342         {
13343                 // convert vertex positions to texcoords
13344                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13345                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13346                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13347                 // calculate distance fade from the projection origin
13348                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13349                 f = bound(0.0f, f, 1.0f);
13350                 c[cornerindex][0] = r * f;
13351                 c[cornerindex][1] = g * f;
13352                 c[cornerindex][2] = b * f;
13353                 c[cornerindex][3] = 1.0f;
13354                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13355         }
13356         if (dynamic)
13357                 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);
13358         else
13359                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13360                         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);
13361 }
13362 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)
13363 {
13364         matrix4x4_t projection;
13365         decalsystem_t *decalsystem;
13366         qboolean dynamic;
13367         dp_model_t *model;
13368         const msurface_t *surface;
13369         const msurface_t *surfaces;
13370         const int *surfacelist;
13371         const texture_t *texture;
13372         int numtriangles;
13373         int numsurfacelist;
13374         int surfacelistindex;
13375         int surfaceindex;
13376         int triangleindex;
13377         float localorigin[3];
13378         float localnormal[3];
13379         float localmins[3];
13380         float localmaxs[3];
13381         float localsize;
13382         //float normal[3];
13383         float planes[6][4];
13384         float angles[3];
13385         bih_t *bih;
13386         int bih_triangles_count;
13387         int bih_triangles[256];
13388         int bih_surfaces[256];
13389
13390         decalsystem = &ent->decalsystem;
13391         model = ent->model;
13392         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13393         {
13394                 R_DecalSystem_Reset(&ent->decalsystem);
13395                 return;
13396         }
13397
13398         if (!model->brush.data_leafs && !cl_decals_models.integer)
13399         {
13400                 if (decalsystem->model)
13401                         R_DecalSystem_Reset(decalsystem);
13402                 return;
13403         }
13404
13405         if (decalsystem->model != model)
13406                 R_DecalSystem_Reset(decalsystem);
13407         decalsystem->model = model;
13408
13409         RSurf_ActiveModelEntity(ent, false, false, false);
13410
13411         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13412         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13413         VectorNormalize(localnormal);
13414         localsize = worldsize*rsurface.inversematrixscale;
13415         localmins[0] = localorigin[0] - localsize;
13416         localmins[1] = localorigin[1] - localsize;
13417         localmins[2] = localorigin[2] - localsize;
13418         localmaxs[0] = localorigin[0] + localsize;
13419         localmaxs[1] = localorigin[1] + localsize;
13420         localmaxs[2] = localorigin[2] + localsize;
13421
13422         //VectorCopy(localnormal, planes[4]);
13423         //VectorVectors(planes[4], planes[2], planes[0]);
13424         AnglesFromVectors(angles, localnormal, NULL, false);
13425         AngleVectors(angles, planes[0], planes[2], planes[4]);
13426         VectorNegate(planes[0], planes[1]);
13427         VectorNegate(planes[2], planes[3]);
13428         VectorNegate(planes[4], planes[5]);
13429         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13430         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13431         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13432         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13433         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13434         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13435
13436 #if 1
13437 // works
13438 {
13439         matrix4x4_t forwardprojection;
13440         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13441         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13442 }
13443 #else
13444 // broken
13445 {
13446         float projectionvector[4][3];
13447         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13448         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13449         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13450         projectionvector[0][0] = planes[0][0] * ilocalsize;
13451         projectionvector[0][1] = planes[1][0] * ilocalsize;
13452         projectionvector[0][2] = planes[2][0] * ilocalsize;
13453         projectionvector[1][0] = planes[0][1] * ilocalsize;
13454         projectionvector[1][1] = planes[1][1] * ilocalsize;
13455         projectionvector[1][2] = planes[2][1] * ilocalsize;
13456         projectionvector[2][0] = planes[0][2] * ilocalsize;
13457         projectionvector[2][1] = planes[1][2] * ilocalsize;
13458         projectionvector[2][2] = planes[2][2] * ilocalsize;
13459         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13460         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13461         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13462         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13463 }
13464 #endif
13465
13466         dynamic = model->surfmesh.isanimated;
13467         numsurfacelist = model->nummodelsurfaces;
13468         surfacelist = model->sortedmodelsurfaces;
13469         surfaces = model->data_surfaces;
13470
13471         bih = NULL;
13472         bih_triangles_count = -1;
13473         if(!dynamic)
13474         {
13475                 if(model->render_bih.numleafs)
13476                         bih = &model->render_bih;
13477                 else if(model->collision_bih.numleafs)
13478                         bih = &model->collision_bih;
13479         }
13480         if(bih)
13481                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13482         if(bih_triangles_count == 0)
13483                 return;
13484         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13485                 return;
13486         if(bih_triangles_count > 0)
13487         {
13488                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13489                 {
13490                         surfaceindex = bih_surfaces[triangleindex];
13491                         surface = surfaces + surfaceindex;
13492                         texture = surface->texture;
13493                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13494                                 continue;
13495                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13496                                 continue;
13497                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13498                 }
13499         }
13500         else
13501         {
13502                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13503                 {
13504                         surfaceindex = surfacelist[surfacelistindex];
13505                         surface = surfaces + surfaceindex;
13506                         // check cull box first because it rejects more than any other check
13507                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13508                                 continue;
13509                         // skip transparent surfaces
13510                         texture = surface->texture;
13511                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13512                                 continue;
13513                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13514                                 continue;
13515                         numtriangles = surface->num_triangles;
13516                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13517                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13518                 }
13519         }
13520 }
13521
13522 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13523 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)
13524 {
13525         int renderentityindex;
13526         float worldmins[3];
13527         float worldmaxs[3];
13528         entity_render_t *ent;
13529
13530         if (!cl_decals_newsystem.integer)
13531                 return;
13532
13533         worldmins[0] = worldorigin[0] - worldsize;
13534         worldmins[1] = worldorigin[1] - worldsize;
13535         worldmins[2] = worldorigin[2] - worldsize;
13536         worldmaxs[0] = worldorigin[0] + worldsize;
13537         worldmaxs[1] = worldorigin[1] + worldsize;
13538         worldmaxs[2] = worldorigin[2] + worldsize;
13539
13540         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13541
13542         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13543         {
13544                 ent = r_refdef.scene.entities[renderentityindex];
13545                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13546                         continue;
13547
13548                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13549         }
13550 }
13551
13552 typedef struct r_decalsystem_splatqueue_s
13553 {
13554         vec3_t worldorigin;
13555         vec3_t worldnormal;
13556         float color[4];
13557         float tcrange[4];
13558         float worldsize;
13559         int decalsequence;
13560 }
13561 r_decalsystem_splatqueue_t;
13562
13563 int r_decalsystem_numqueued = 0;
13564 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13565
13566 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)
13567 {
13568         r_decalsystem_splatqueue_t *queue;
13569
13570         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13571                 return;
13572
13573         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13574         VectorCopy(worldorigin, queue->worldorigin);
13575         VectorCopy(worldnormal, queue->worldnormal);
13576         Vector4Set(queue->color, r, g, b, a);
13577         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13578         queue->worldsize = worldsize;
13579         queue->decalsequence = cl.decalsequence++;
13580 }
13581
13582 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13583 {
13584         int i;
13585         r_decalsystem_splatqueue_t *queue;
13586
13587         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13588                 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);
13589         r_decalsystem_numqueued = 0;
13590 }
13591
13592 extern cvar_t cl_decals_max;
13593 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13594 {
13595         int i;
13596         decalsystem_t *decalsystem = &ent->decalsystem;
13597         int numdecals;
13598         int killsequence;
13599         tridecal_t *decal;
13600         float frametime;
13601         float lifetime;
13602
13603         if (!decalsystem->numdecals)
13604                 return;
13605
13606         if (r_showsurfaces.integer)
13607                 return;
13608
13609         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13610         {
13611                 R_DecalSystem_Reset(decalsystem);
13612                 return;
13613         }
13614
13615         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13616         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13617
13618         if (decalsystem->lastupdatetime)
13619                 frametime = (cl.time - decalsystem->lastupdatetime);
13620         else
13621                 frametime = 0;
13622         decalsystem->lastupdatetime = cl.time;
13623         decal = decalsystem->decals;
13624         numdecals = decalsystem->numdecals;
13625
13626         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13627         {
13628                 if (decal->color4ub[0][3])
13629                 {
13630                         decal->lived += frametime;
13631                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13632                         {
13633                                 memset(decal, 0, sizeof(*decal));
13634                                 if (decalsystem->freedecal > i)
13635                                         decalsystem->freedecal = i;
13636                         }
13637                 }
13638         }
13639         decal = decalsystem->decals;
13640         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13641                 numdecals--;
13642
13643         // collapse the array by shuffling the tail decals into the gaps
13644         for (;;)
13645         {
13646                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13647                         decalsystem->freedecal++;
13648                 if (decalsystem->freedecal == numdecals)
13649                         break;
13650                 decal[decalsystem->freedecal] = decal[--numdecals];
13651         }
13652
13653         decalsystem->numdecals = numdecals;
13654
13655         if (numdecals <= 0)
13656         {
13657                 // if there are no decals left, reset decalsystem
13658                 R_DecalSystem_Reset(decalsystem);
13659         }
13660 }
13661
13662 extern skinframe_t *decalskinframe;
13663 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13664 {
13665         int i;
13666         decalsystem_t *decalsystem = &ent->decalsystem;
13667         int numdecals;
13668         tridecal_t *decal;
13669         float faderate;
13670         float alpha;
13671         float *v3f;
13672         float *c4f;
13673         float *t2f;
13674         const int *e;
13675         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13676         int numtris = 0;
13677
13678         numdecals = decalsystem->numdecals;
13679         if (!numdecals)
13680                 return;
13681
13682         if (r_showsurfaces.integer)
13683                 return;
13684
13685         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13686         {
13687                 R_DecalSystem_Reset(decalsystem);
13688                 return;
13689         }
13690
13691         // if the model is static it doesn't matter what value we give for
13692         // wantnormals and wanttangents, so this logic uses only rules applicable
13693         // to a model, knowing that they are meaningless otherwise
13694         if (ent == r_refdef.scene.worldentity)
13695                 RSurf_ActiveWorldEntity();
13696         else
13697                 RSurf_ActiveModelEntity(ent, false, false, false);
13698
13699         decalsystem->lastupdatetime = cl.time;
13700         decal = decalsystem->decals;
13701
13702         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13703
13704         // update vertex positions for animated models
13705         v3f = decalsystem->vertex3f;
13706         c4f = decalsystem->color4f;
13707         t2f = decalsystem->texcoord2f;
13708         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13709         {
13710                 if (!decal->color4ub[0][3])
13711                         continue;
13712
13713                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13714                         continue;
13715
13716                 // update color values for fading decals
13717                 if (decal->lived >= cl_decals_time.value)
13718                 {
13719                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13720                         alpha *= (1.0f/255.0f);
13721                 }
13722                 else
13723                         alpha = 1.0f/255.0f;
13724
13725                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13726                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13727                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13728                 c4f[ 3] = 1;
13729                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13730                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13731                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13732                 c4f[ 7] = 1;
13733                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13734                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13735                 c4f[10] = decal->color4ub[2][2] * alpha;
13736                 c4f[11] = 1;
13737
13738                 t2f[0] = decal->texcoord2f[0][0];
13739                 t2f[1] = decal->texcoord2f[0][1];
13740                 t2f[2] = decal->texcoord2f[1][0];
13741                 t2f[3] = decal->texcoord2f[1][1];
13742                 t2f[4] = decal->texcoord2f[2][0];
13743                 t2f[5] = decal->texcoord2f[2][1];
13744
13745                 // update vertex positions for animated models
13746                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13747                 {
13748                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13749                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13750                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13751                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13752                 }
13753                 else
13754                 {
13755                         VectorCopy(decal->vertex3f[0], v3f);
13756                         VectorCopy(decal->vertex3f[1], v3f + 3);
13757                         VectorCopy(decal->vertex3f[2], v3f + 6);
13758                 }
13759
13760                 if (r_refdef.fogenabled)
13761                 {
13762                         alpha = RSurf_FogVertex(v3f);
13763                         VectorScale(c4f, alpha, c4f);
13764                         alpha = RSurf_FogVertex(v3f + 3);
13765                         VectorScale(c4f + 4, alpha, c4f + 4);
13766                         alpha = RSurf_FogVertex(v3f + 6);
13767                         VectorScale(c4f + 8, alpha, c4f + 8);
13768                 }
13769
13770                 v3f += 9;
13771                 c4f += 12;
13772                 t2f += 6;
13773                 numtris++;
13774         }
13775
13776         if (numtris > 0)
13777         {
13778                 r_refdef.stats.drawndecals += numtris;
13779
13780                 // now render the decals all at once
13781                 // (this assumes they all use one particle font texture!)
13782                 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);
13783                 R_Mesh_ResetTextureState();
13784                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13785                 GL_DepthMask(false);
13786                 GL_DepthRange(0, 1);
13787                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13788                 GL_DepthTest(true);
13789                 GL_CullFace(GL_NONE);
13790                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13791                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13792                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13793         }
13794 }
13795
13796 static void R_DrawModelDecals(void)
13797 {
13798         int i, numdecals;
13799
13800         // fade faster when there are too many decals
13801         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13802         for (i = 0;i < r_refdef.scene.numentities;i++)
13803                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13804
13805         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13806         for (i = 0;i < r_refdef.scene.numentities;i++)
13807                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13808                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13809
13810         R_DecalSystem_ApplySplatEntitiesQueue();
13811
13812         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13813         for (i = 0;i < r_refdef.scene.numentities;i++)
13814                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13815
13816         r_refdef.stats.totaldecals += numdecals;
13817
13818         if (r_showsurfaces.integer)
13819                 return;
13820
13821         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13822
13823         for (i = 0;i < r_refdef.scene.numentities;i++)
13824         {
13825                 if (!r_refdef.viewcache.entityvisible[i])
13826                         continue;
13827                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13828                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13829         }
13830 }
13831
13832 extern cvar_t mod_collision_bih;
13833 void R_DrawDebugModel(void)
13834 {
13835         entity_render_t *ent = rsurface.entity;
13836         int i, j, k, l, flagsmask;
13837         const msurface_t *surface;
13838         dp_model_t *model = ent->model;
13839         vec3_t v;
13840
13841         switch(vid.renderpath)
13842         {
13843         case RENDERPATH_GL11:
13844         case RENDERPATH_GL13:
13845         case RENDERPATH_GL20:
13846         case RENDERPATH_CGGL:
13847                 break;
13848         case RENDERPATH_D3D9:
13849                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13850                 return;
13851         case RENDERPATH_D3D10:
13852                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13853                 return;
13854         case RENDERPATH_D3D11:
13855                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13856                 return;
13857         }
13858
13859         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13860
13861         R_Mesh_ResetTextureState();
13862         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13863         GL_DepthRange(0, 1);
13864         GL_DepthTest(!r_showdisabledepthtest.integer);
13865         GL_DepthMask(false);
13866         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13867
13868         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13869         {
13870                 int triangleindex;
13871                 int bihleafindex;
13872                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13873                 const q3mbrush_t *brush;
13874                 const bih_t *bih = &model->collision_bih;
13875                 const bih_leaf_t *bihleaf;
13876                 float vertex3f[3][3];
13877                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13878                 cullbox = false;
13879                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13880                 {
13881                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13882                                 continue;
13883                         switch (bihleaf->type)
13884                         {
13885                         case BIH_BRUSH:
13886                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13887                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13888                                 {
13889                                         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);
13890                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13891                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13892                                 }
13893                                 break;
13894                         case BIH_COLLISIONTRIANGLE:
13895                                 triangleindex = bihleaf->itemindex;
13896                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13897                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13898                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13899                                 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);
13900                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13901                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13902                                 break;
13903                         case BIH_RENDERTRIANGLE:
13904                                 triangleindex = bihleaf->itemindex;
13905                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13906                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13907                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13908                                 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);
13909                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13910                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13911                                 break;
13912                         }
13913                 }
13914         }
13915
13916         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13917
13918         if (r_showtris.integer || r_shownormals.integer)
13919         {
13920                 if (r_showdisabledepthtest.integer)
13921                 {
13922                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13923                         GL_DepthMask(false);
13924                 }
13925                 else
13926                 {
13927                         GL_BlendFunc(GL_ONE, GL_ZERO);
13928                         GL_DepthMask(true);
13929                 }
13930                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13931                 {
13932                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13933                                 continue;
13934                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13935                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13936                         {
13937                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13938                                 if (r_showtris.value > 0)
13939                                 {
13940                                         if (!rsurface.texture->currentlayers->depthmask)
13941                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13942                                         else if (ent == r_refdef.scene.worldentity)
13943                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13944                                         else
13945                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13946                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13947                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13948                                         RSurf_DrawBatch();
13949                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13950                                         CHECKGLERROR
13951                                 }
13952                                 if (r_shownormals.value < 0)
13953                                 {
13954                                         qglBegin(GL_LINES);
13955                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13956                                         {
13957                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13958                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13959                                                 qglVertex3f(v[0], v[1], v[2]);
13960                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13961                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13962                                                 qglVertex3f(v[0], v[1], v[2]);
13963                                         }
13964                                         qglEnd();
13965                                         CHECKGLERROR
13966                                 }
13967                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13968                                 {
13969                                         qglBegin(GL_LINES);
13970                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13971                                         {
13972                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13973                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13974                                                 qglVertex3f(v[0], v[1], v[2]);
13975                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13976                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13977                                                 qglVertex3f(v[0], v[1], v[2]);
13978                                         }
13979                                         qglEnd();
13980                                         CHECKGLERROR
13981                                         qglBegin(GL_LINES);
13982                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13983                                         {
13984                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13985                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13986                                                 qglVertex3f(v[0], v[1], v[2]);
13987                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13988                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13989                                                 qglVertex3f(v[0], v[1], v[2]);
13990                                         }
13991                                         qglEnd();
13992                                         CHECKGLERROR
13993                                         qglBegin(GL_LINES);
13994                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13995                                         {
13996                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13997                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13998                                                 qglVertex3f(v[0], v[1], v[2]);
13999                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14000                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14001                                                 qglVertex3f(v[0], v[1], v[2]);
14002                                         }
14003                                         qglEnd();
14004                                         CHECKGLERROR
14005                                 }
14006                         }
14007                 }
14008                 rsurface.texture = NULL;
14009         }
14010 }
14011
14012 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14013 int r_maxsurfacelist = 0;
14014 const msurface_t **r_surfacelist = NULL;
14015 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14016 {
14017         int i, j, endj, flagsmask;
14018         dp_model_t *model = r_refdef.scene.worldmodel;
14019         msurface_t *surfaces;
14020         unsigned char *update;
14021         int numsurfacelist = 0;
14022         if (model == NULL)
14023                 return;
14024
14025         if (r_maxsurfacelist < model->num_surfaces)
14026         {
14027                 r_maxsurfacelist = model->num_surfaces;
14028                 if (r_surfacelist)
14029                         Mem_Free((msurface_t**)r_surfacelist);
14030                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14031         }
14032
14033         RSurf_ActiveWorldEntity();
14034
14035         surfaces = model->data_surfaces;
14036         update = model->brushq1.lightmapupdateflags;
14037
14038         // update light styles on this submodel
14039         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14040         {
14041                 model_brush_lightstyleinfo_t *style;
14042                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14043                 {
14044                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14045                         {
14046                                 int *list = style->surfacelist;
14047                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14048                                 for (j = 0;j < style->numsurfaces;j++)
14049                                         update[list[j]] = true;
14050                         }
14051                 }
14052         }
14053
14054         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14055
14056         if (debug)
14057         {
14058                 R_DrawDebugModel();
14059                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14060                 return;
14061         }
14062
14063         rsurface.lightmaptexture = NULL;
14064         rsurface.deluxemaptexture = NULL;
14065         rsurface.uselightmaptexture = false;
14066         rsurface.texture = NULL;
14067         rsurface.rtlight = NULL;
14068         numsurfacelist = 0;
14069         // add visible surfaces to draw list
14070         for (i = 0;i < model->nummodelsurfaces;i++)
14071         {
14072                 j = model->sortedmodelsurfaces[i];
14073                 if (r_refdef.viewcache.world_surfacevisible[j])
14074                         r_surfacelist[numsurfacelist++] = surfaces + j;
14075         }
14076         // update lightmaps if needed
14077         if (model->brushq1.firstrender)
14078         {
14079                 model->brushq1.firstrender = false;
14080                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14081                         if (update[j])
14082                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14083         }
14084         else if (update)
14085         {
14086                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14087                         if (r_refdef.viewcache.world_surfacevisible[j])
14088                                 if (update[j])
14089                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14090         }
14091         // don't do anything if there were no surfaces
14092         if (!numsurfacelist)
14093         {
14094                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14095                 return;
14096         }
14097         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14098         GL_AlphaTest(false);
14099
14100         // add to stats if desired
14101         if (r_speeds.integer && !skysurfaces && !depthonly)
14102         {
14103                 r_refdef.stats.world_surfaces += numsurfacelist;
14104                 for (j = 0;j < numsurfacelist;j++)
14105                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14106         }
14107
14108         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14109 }
14110
14111 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14112 {
14113         int i, j, endj, flagsmask;
14114         dp_model_t *model = ent->model;
14115         msurface_t *surfaces;
14116         unsigned char *update;
14117         int numsurfacelist = 0;
14118         if (model == NULL)
14119                 return;
14120
14121         if (r_maxsurfacelist < model->num_surfaces)
14122         {
14123                 r_maxsurfacelist = model->num_surfaces;
14124                 if (r_surfacelist)
14125                         Mem_Free((msurface_t **)r_surfacelist);
14126                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14127         }
14128
14129         // if the model is static it doesn't matter what value we give for
14130         // wantnormals and wanttangents, so this logic uses only rules applicable
14131         // to a model, knowing that they are meaningless otherwise
14132         if (ent == r_refdef.scene.worldentity)
14133                 RSurf_ActiveWorldEntity();
14134         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14135                 RSurf_ActiveModelEntity(ent, false, false, false);
14136         else if (prepass)
14137                 RSurf_ActiveModelEntity(ent, true, true, true);
14138         else if (depthonly)
14139         {
14140                 switch (vid.renderpath)
14141                 {
14142                 case RENDERPATH_GL20:
14143                 case RENDERPATH_CGGL:
14144                 case RENDERPATH_D3D9:
14145                 case RENDERPATH_D3D10:
14146                 case RENDERPATH_D3D11:
14147                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14148                         break;
14149                 case RENDERPATH_GL13:
14150                 case RENDERPATH_GL11:
14151                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14152                         break;
14153                 }
14154         }
14155         else
14156         {
14157                 switch (vid.renderpath)
14158                 {
14159                 case RENDERPATH_GL20:
14160                 case RENDERPATH_CGGL:
14161                 case RENDERPATH_D3D9:
14162                 case RENDERPATH_D3D10:
14163                 case RENDERPATH_D3D11:
14164                         RSurf_ActiveModelEntity(ent, true, true, false);
14165                         break;
14166                 case RENDERPATH_GL13:
14167                 case RENDERPATH_GL11:
14168                         RSurf_ActiveModelEntity(ent, true, false, false);
14169                         break;
14170                 }
14171         }
14172
14173         surfaces = model->data_surfaces;
14174         update = model->brushq1.lightmapupdateflags;
14175
14176         // update light styles
14177         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14178         {
14179                 model_brush_lightstyleinfo_t *style;
14180                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14181                 {
14182                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14183                         {
14184                                 int *list = style->surfacelist;
14185                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14186                                 for (j = 0;j < style->numsurfaces;j++)
14187                                         update[list[j]] = true;
14188                         }
14189                 }
14190         }
14191
14192         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14193
14194         if (debug)
14195         {
14196                 R_DrawDebugModel();
14197                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14198                 return;
14199         }
14200
14201         rsurface.lightmaptexture = NULL;
14202         rsurface.deluxemaptexture = NULL;
14203         rsurface.uselightmaptexture = false;
14204         rsurface.texture = NULL;
14205         rsurface.rtlight = NULL;
14206         numsurfacelist = 0;
14207         // add visible surfaces to draw list
14208         for (i = 0;i < model->nummodelsurfaces;i++)
14209                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14210         // don't do anything if there were no surfaces
14211         if (!numsurfacelist)
14212         {
14213                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14214                 return;
14215         }
14216         // update lightmaps if needed
14217         if (update)
14218         {
14219                 int updated = 0;
14220                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14221                 {
14222                         if (update[j])
14223                         {
14224                                 updated++;
14225                                 R_BuildLightMap(ent, surfaces + j);
14226                         }
14227                 }
14228         }
14229         if (update)
14230                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14231                         if (update[j])
14232                                 R_BuildLightMap(ent, surfaces + j);
14233         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14234         GL_AlphaTest(false);
14235
14236         // add to stats if desired
14237         if (r_speeds.integer && !skysurfaces && !depthonly)
14238         {
14239                 r_refdef.stats.entities_surfaces += numsurfacelist;
14240                 for (j = 0;j < numsurfacelist;j++)
14241                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14242         }
14243
14244         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14245 }
14246
14247 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14248 {
14249         static texture_t texture;
14250         static msurface_t surface;
14251         const msurface_t *surfacelist = &surface;
14252
14253         // fake enough texture and surface state to render this geometry
14254
14255         texture.update_lastrenderframe = -1; // regenerate this texture
14256         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14257         texture.currentskinframe = skinframe;
14258         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14259         texture.offsetmapping = OFFSETMAPPING_OFF;
14260         texture.offsetscale = 1;
14261         texture.specularscalemod = 1;
14262         texture.specularpowermod = 1;
14263
14264         surface.texture = &texture;
14265         surface.num_triangles = numtriangles;
14266         surface.num_firsttriangle = firsttriangle;
14267         surface.num_vertices = numvertices;
14268         surface.num_firstvertex = firstvertex;
14269
14270         // now render it
14271         rsurface.texture = R_GetCurrentTexture(surface.texture);
14272         rsurface.lightmaptexture = NULL;
14273         rsurface.deluxemaptexture = NULL;
14274         rsurface.uselightmaptexture = false;
14275         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14276 }
14277
14278 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)
14279 {
14280         static msurface_t surface;
14281         const msurface_t *surfacelist = &surface;
14282
14283         // fake enough texture and surface state to render this geometry
14284
14285         surface.texture = texture;
14286         surface.num_triangles = numtriangles;
14287         surface.num_firsttriangle = firsttriangle;
14288         surface.num_vertices = numvertices;
14289         surface.num_firstvertex = firstvertex;
14290
14291         // now render it
14292         rsurface.texture = R_GetCurrentTexture(surface.texture);
14293         rsurface.lightmaptexture = NULL;
14294         rsurface.deluxemaptexture = NULL;
14295         rsurface.uselightmaptexture = false;
14296         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14297 }