]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
updated glsl and cg (now also directly compiled as hlsl) shaders - integrated the...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
146
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
170
171 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
172
173 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | 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 "/* The engine may define the following macros:\n"
577 "#define VERTEX_SHADER\n"
578 "#define GEOMETRY_SHADER\n"
579 "#define FRAGMENT_SHADER\n"
580 "#define MODE_GENERIC\n"
581 "#define MODE_POSTPROCESS\n"
582 "#define MODE_DEPTH_OR_SHADOW\n"
583 "#define MODE_FLATCOLOR\n"
584 "#define MODE_VERTEXCOLOR\n"
585 "#define MODE_LIGHTMAP\n"
586 "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
587 "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
588 "#define MODE_LIGHTDIRECTION\n"
589 "#define MODE_LIGHTSOURCE\n"
590 "#define MODE_REFRACTION\n"
591 "#define MODE_WATER\n"
592 "#define MODE_SHOWDEPTH\n"
593 "#define MODE_DEFERREDGEOMETRY\n"
594 "#define MODE_DEFERREDLIGHTSOURCE\n"
595 "#define USEDIFFUSE\n"
596 "#define USEVERTEXTEXTUREBLEND\n"
597 "#define USEVIEWTINT\n"
598 "#define USECOLORMAPPING\n"
599 "#define USESATURATION\n"
600 "#define USEFOGINSIDE\n"
601 "#define USEFOGOUTSIDE\n"
602 "#define USEFOGHEIGHTTEXTURE\n"
603 "#define USEGAMMARAMPS\n"
604 "#define USECUBEFILTER\n"
605 "#define USEGLOW\n"
606 "#define USEBLOOM\n"
607 "#define USESPECULAR\n"
608 "#define USEPOSTPROCESSING\n"
609 "#define USEEXACTSPECULARMATH\n"
610 "#define USEREFLECTION\n"
611 "#define USEOFFSETMAPPING\n"
612 "#define USEOFFSETMAPPING_RELIEFMAPPING\n"
613 "#define USESHADOWMAPRECT\n"
614 "#define USESHADOWMAPCUBE\n"
615 "#define USESHADOWMAP2D\n"
616 "#define USESHADOWMAPPCF 1\n"
617 "#define USESHADOWMAPPCF 2\n"
618 "#define USESHADOWSAMPLER\n"
619 "#define USESHADOWMAPVSDCT\n"
620 "#define USESHADOWMAPORTHO\n"
621 "#define USEDEFERREDLIGHTMAP\n"
622 "#define USEALPHAKILL\n"
623 "#define USEREFLECTCUBE\n"
624 "*/\n"
625 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
626 "// written by Forest 'LordHavoc' Hale\n"
627 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
628 "\n"
629 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
630 "# define USEFOG\n"
631 "#endif\n"
632 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
633 "#define USELIGHTMAP\n"
634 "#endif\n"
635 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
636 "#define USEEYEVECTOR\n"
637 "#endif\n"
638 "\n"
639 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
640 "# extension GL_ARB_texture_rectangle : enable\n"
641 "#endif\n"
642 "\n"
643 "#ifdef USESHADOWMAP2D\n"
644 "# ifdef GL_EXT_gpu_shader4\n"
645 "#   extension GL_EXT_gpu_shader4 : enable\n"
646 "# endif\n"
647 "# ifdef GL_ARB_texture_gather\n"
648 "#   extension GL_ARB_texture_gather : enable\n"
649 "# else\n"
650 "#   ifdef GL_AMD_texture_texture4\n"
651 "#     extension GL_AMD_texture_texture4 : enable\n"
652 "#   endif\n"
653 "# endif\n"
654 "#endif\n"
655 "\n"
656 "#ifdef USESHADOWMAPCUBE\n"
657 "# extension GL_EXT_gpu_shader4 : enable\n"
658 "#endif\n"
659 "\n"
660 "//#ifdef USESHADOWSAMPLER\n"
661 "//# extension GL_ARB_shadow : enable\n"
662 "//#endif\n"
663 "\n"
664 "//#ifdef __GLSL_CG_DATA_TYPES\n"
665 "//# define myhalf half\n"
666 "//# define myhalf2 half2\n"
667 "//# define myhalf3 half3\n"
668 "//# define myhalf4 half4\n"
669 "//#else\n"
670 "# define myhalf float\n"
671 "# define myhalf2 vec2\n"
672 "# define myhalf3 vec3\n"
673 "# define myhalf4 vec4\n"
674 "//#endif\n"
675 "\n"
676 "#ifdef VERTEX_SHADER\n"
677 "uniform mat4 ModelViewProjectionMatrix;\n"
678 "#endif\n"
679 "\n"
680 "#ifdef MODE_DEPTH_OR_SHADOW\n"
681 "#ifdef VERTEX_SHADER\n"
682 "void main(void)\n"
683 "{\n"
684 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
685 "}\n"
686 "#endif\n"
687 "#else // !MODE_DEPTH_ORSHADOW\n"
688 "\n"
689 "\n"
690 "\n"
691 "\n"
692 "#ifdef MODE_SHOWDEPTH\n"
693 "#ifdef VERTEX_SHADER\n"
694 "void main(void)\n"
695 "{\n"
696 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
697 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
698 "}\n"
699 "#endif\n"
700 "\n"
701 "#ifdef FRAGMENT_SHADER\n"
702 "void main(void)\n"
703 "{\n"
704 "       gl_FragColor = gl_Color;\n"
705 "}\n"
706 "#endif\n"
707 "#else // !MODE_SHOWDEPTH\n"
708 "\n"
709 "\n"
710 "\n"
711 "\n"
712 "#ifdef MODE_POSTPROCESS\n"
713 "varying vec2 TexCoord1;\n"
714 "varying vec2 TexCoord2;\n"
715 "\n"
716 "#ifdef VERTEX_SHADER\n"
717 "void main(void)\n"
718 "{\n"
719 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
720 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
721 "#ifdef USEBLOOM\n"
722 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
723 "#endif\n"
724 "}\n"
725 "#endif\n"
726 "\n"
727 "#ifdef FRAGMENT_SHADER\n"
728 "uniform sampler2D Texture_First;\n"
729 "#ifdef USEBLOOM\n"
730 "uniform sampler2D Texture_Second;\n"
731 "uniform vec4 BloomColorSubtract;\n"
732 "#endif\n"
733 "#ifdef USEGAMMARAMPS\n"
734 "uniform sampler2D Texture_GammaRamps;\n"
735 "#endif\n"
736 "#ifdef USESATURATION\n"
737 "uniform float Saturation;\n"
738 "#endif\n"
739 "#ifdef USEVIEWTINT\n"
740 "uniform vec4 ViewTintColor;\n"
741 "#endif\n"
742 "//uncomment these if you want to use them:\n"
743 "uniform vec4 UserVec1;\n"
744 "uniform vec4 UserVec2;\n"
745 "// uniform vec4 UserVec3;\n"
746 "// uniform vec4 UserVec4;\n"
747 "// uniform float ClientTime;\n"
748 "uniform vec2 PixelSize;\n"
749 "void main(void)\n"
750 "{\n"
751 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
752 "#ifdef USEBLOOM\n"
753 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
754 "#endif\n"
755 "#ifdef USEVIEWTINT\n"
756 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
757 "#endif\n"
758 "\n"
759 "#ifdef USEPOSTPROCESSING\n"
760 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
761 "// 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"
762 "       float sobel = 1.0;\n"
763 "       // vec2 ts = textureSize(Texture_First, 0);\n"
764 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
765 "       vec2 px = PixelSize;\n"
766 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
767 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
768 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
769 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
770 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
771 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
772 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
773 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
774 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
775 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
776 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
777 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
778 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
779 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
780 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
781 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
782 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
783 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
784 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
785 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
786 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
787 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
788 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
789 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
790 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
791 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
792 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
793 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
794 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
795 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
796 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
797 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
798 "#endif\n"
799 "\n"
800 "#ifdef USESATURATION\n"
801 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
802 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
803 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
804 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
805 "#endif\n"
806 "\n"
807 "#ifdef USEGAMMARAMPS\n"
808 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
809 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
810 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
811 "#endif\n"
812 "}\n"
813 "#endif\n"
814 "#else // !MODE_POSTPROCESS\n"
815 "\n"
816 "\n"
817 "\n"
818 "\n"
819 "#ifdef MODE_GENERIC\n"
820 "#ifdef USEDIFFUSE\n"
821 "varying vec2 TexCoord1;\n"
822 "#endif\n"
823 "#ifdef USESPECULAR\n"
824 "varying vec2 TexCoord2;\n"
825 "#endif\n"
826 "#ifdef VERTEX_SHADER\n"
827 "void main(void)\n"
828 "{\n"
829 "       gl_FrontColor = gl_Color;\n"
830 "#ifdef USEDIFFUSE\n"
831 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
832 "#endif\n"
833 "#ifdef USESPECULAR\n"
834 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
835 "#endif\n"
836 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
837 "}\n"
838 "#endif\n"
839 "\n"
840 "#ifdef FRAGMENT_SHADER\n"
841 "#ifdef USEDIFFUSE\n"
842 "uniform sampler2D Texture_First;\n"
843 "#endif\n"
844 "#ifdef USESPECULAR\n"
845 "uniform sampler2D Texture_Second;\n"
846 "#endif\n"
847 "\n"
848 "void main(void)\n"
849 "{\n"
850 "       gl_FragColor = gl_Color;\n"
851 "#ifdef USEDIFFUSE\n"
852 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
853 "#endif\n"
854 "\n"
855 "#ifdef USESPECULAR\n"
856 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
857 "# ifdef USECOLORMAPPING\n"
858 "       gl_FragColor *= tex2;\n"
859 "# endif\n"
860 "# ifdef USEGLOW\n"
861 "       gl_FragColor += tex2;\n"
862 "# endif\n"
863 "# ifdef USEVERTEXTEXTUREBLEND\n"
864 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
865 "# endif\n"
866 "#endif\n"
867 "}\n"
868 "#endif\n"
869 "#else // !MODE_GENERIC\n"
870 "\n"
871 "\n"
872 "\n"
873 "\n"
874 "#ifdef MODE_BLOOMBLUR\n"
875 "varying TexCoord;\n"
876 "#ifdef VERTEX_SHADER\n"
877 "void main(void)\n"
878 "{\n"
879 "       gl_FrontColor = gl_Color;\n"
880 "       TexCoord = gl_MultiTexCoord0.xy;\n"
881 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
882 "}\n"
883 "#endif\n"
884 "\n"
885 "#ifdef FRAGMENT_SHADER\n"
886 "uniform sampler2D Texture_First;\n"
887 "uniform vec4 BloomBlur_Parameters;\n"
888 "\n"
889 "void main(void)\n"
890 "{\n"
891 "       int i;\n"
892 "       vec2 tc = TexCoord;\n"
893 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
894 "       tc += BloomBlur_Parameters.xy;\n"
895 "       for (i = 1;i < SAMPLES;i++)\n"
896 "       {\n"
897 "               color += texture2D(Texture_First, tc).rgb;\n"
898 "               tc += BloomBlur_Parameters.xy;\n"
899 "       }\n"
900 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
901 "}\n"
902 "#endif\n"
903 "#else // !MODE_BLOOMBLUR\n"
904 "#ifdef MODE_REFRACTION\n"
905 "varying vec2 TexCoord;\n"
906 "varying vec4 ModelViewProjectionPosition;\n"
907 "uniform mat4 TexMatrix;\n"
908 "#ifdef VERTEX_SHADER\n"
909 "\n"
910 "void main(void)\n"
911 "{\n"
912 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
934 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
935 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
936 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
937 "       // FIXME temporary hack to detect the case that the reflection\n"
938 "       // gets blackened at edges due to leaving the area that contains actual\n"
939 "       // content.\n"
940 "       // Remove this 'ack once we have a better way to stop this thing from\n"
941 "       // 'appening.\n"
942 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
943 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
946 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
947 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
948 "}\n"
949 "#endif\n"
950 "#else // !MODE_REFRACTION\n"
951 "\n"
952 "\n"
953 "\n"
954 "\n"
955 "#ifdef MODE_WATER\n"
956 "varying vec2 TexCoord;\n"
957 "varying vec3 EyeVector;\n"
958 "varying vec4 ModelViewProjectionPosition;\n"
959 "#ifdef VERTEX_SHADER\n"
960 "uniform vec3 EyePosition;\n"
961 "uniform mat4 TexMatrix;\n"
962 "\n"
963 "void main(void)\n"
964 "{\n"
965 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
966 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
967 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
968 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
969 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
970 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
971 "       ModelViewProjectionPosition = gl_Position;\n"
972 "}\n"
973 "#endif\n"
974 "\n"
975 "#ifdef FRAGMENT_SHADER\n"
976 "uniform sampler2D Texture_Normal;\n"
977 "uniform sampler2D Texture_Refraction;\n"
978 "uniform sampler2D Texture_Reflection;\n"
979 "\n"
980 "uniform vec4 DistortScaleRefractReflect;\n"
981 "uniform vec4 ScreenScaleRefractReflect;\n"
982 "uniform vec4 ScreenCenterRefractReflect;\n"
983 "uniform vec4 RefractColor;\n"
984 "uniform vec4 ReflectColor;\n"
985 "uniform float ReflectFactor;\n"
986 "uniform float ReflectOffset;\n"
987 "\n"
988 "void main(void)\n"
989 "{\n"
990 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
991 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
992 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
993 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
994 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
995 "       // FIXME temporary hack to detect the case that the reflection\n"
996 "       // gets blackened at edges due to leaving the area that contains actual\n"
997 "       // content.\n"
998 "       // Remove this 'ack once we have a better way to stop this thing from\n"
999 "       // 'appening.\n"
1000 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1001 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1002 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1003 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1004 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1005 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1006 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1007 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1008 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1009 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1010 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1011 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
1012 "}\n"
1013 "#endif\n"
1014 "#else // !MODE_WATER\n"
1015 "\n"
1016 "\n"
1017 "\n"
1018 "\n"
1019 "// common definitions between vertex shader and fragment shader:\n"
1020 "\n"
1021 "varying vec2 TexCoord;\n"
1022 "#ifdef USEVERTEXTEXTUREBLEND\n"
1023 "varying vec2 TexCoord2;\n"
1024 "#endif\n"
1025 "#ifdef USELIGHTMAP\n"
1026 "varying vec2 TexCoordLightmap;\n"
1027 "#endif\n"
1028 "\n"
1029 "#ifdef MODE_LIGHTSOURCE\n"
1030 "varying vec3 CubeVector;\n"
1031 "#endif\n"
1032 "\n"
1033 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1034 "varying vec3 LightVector;\n"
1035 "#endif\n"
1036 "\n"
1037 "#ifdef USEEYEVECTOR\n"
1038 "varying vec3 EyeVector;\n"
1039 "#endif\n"
1040 "#ifdef USEFOG\n"
1041 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1042 "#endif\n"
1043 "\n"
1044 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1045 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1046 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1047 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1048 "#endif\n"
1049 "\n"
1050 "#ifdef USEREFLECTION\n"
1051 "varying vec4 ModelViewProjectionPosition;\n"
1052 "#endif\n"
1053 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1054 "uniform vec3 LightPosition;\n"
1055 "varying vec4 ModelViewPosition;\n"
1056 "#endif\n"
1057 "\n"
1058 "#ifdef MODE_LIGHTSOURCE\n"
1059 "uniform vec3 LightPosition;\n"
1060 "#endif\n"
1061 "uniform vec3 EyePosition;\n"
1062 "#ifdef MODE_LIGHTDIRECTION\n"
1063 "uniform vec3 LightDir;\n"
1064 "#endif\n"
1065 "uniform vec4 FogPlane;\n"
1066 "\n"
1067 "#ifdef USESHADOWMAPORTHO\n"
1068 "varying vec3 ShadowMapTC;\n"
1069 "#endif\n"
1070 "\n"
1071 "\n"
1072 "\n"
1073 "\n"
1074 "\n"
1075 "// 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"
1076 "\n"
1077 "// fragment shader specific:\n"
1078 "#ifdef FRAGMENT_SHADER\n"
1079 "\n"
1080 "uniform sampler2D Texture_Normal;\n"
1081 "uniform sampler2D Texture_Color;\n"
1082 "uniform sampler2D Texture_Gloss;\n"
1083 "#ifdef USEGLOW\n"
1084 "uniform sampler2D Texture_Glow;\n"
1085 "#endif\n"
1086 "#ifdef USEVERTEXTEXTUREBLEND\n"
1087 "uniform sampler2D Texture_SecondaryNormal;\n"
1088 "uniform sampler2D Texture_SecondaryColor;\n"
1089 "uniform sampler2D Texture_SecondaryGloss;\n"
1090 "#ifdef USEGLOW\n"
1091 "uniform sampler2D Texture_SecondaryGlow;\n"
1092 "#endif\n"
1093 "#endif\n"
1094 "#ifdef USECOLORMAPPING\n"
1095 "uniform sampler2D Texture_Pants;\n"
1096 "uniform sampler2D Texture_Shirt;\n"
1097 "#endif\n"
1098 "#ifdef USEFOG\n"
1099 "#ifdef USEFOGHEIGHTTEXTURE\n"
1100 "uniform sampler2D Texture_FogHeightTexture;\n"
1101 "#endif\n"
1102 "uniform sampler2D Texture_FogMask;\n"
1103 "#endif\n"
1104 "#ifdef USELIGHTMAP\n"
1105 "uniform sampler2D Texture_Lightmap;\n"
1106 "#endif\n"
1107 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1108 "uniform sampler2D Texture_Deluxemap;\n"
1109 "#endif\n"
1110 "#ifdef USEREFLECTION\n"
1111 "uniform sampler2D Texture_Reflection;\n"
1112 "#endif\n"
1113 "\n"
1114 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1115 "uniform sampler2D Texture_ScreenDepth;\n"
1116 "uniform sampler2D Texture_ScreenNormalMap;\n"
1117 "#endif\n"
1118 "#ifdef USEDEFERREDLIGHTMAP\n"
1119 "uniform sampler2D Texture_ScreenDiffuse;\n"
1120 "uniform sampler2D Texture_ScreenSpecular;\n"
1121 "#endif\n"
1122 "\n"
1123 "uniform myhalf3 Color_Pants;\n"
1124 "uniform myhalf3 Color_Shirt;\n"
1125 "uniform myhalf3 FogColor;\n"
1126 "\n"
1127 "#ifdef USEFOG\n"
1128 "uniform float FogRangeRecip;\n"
1129 "uniform float FogPlaneViewDist;\n"
1130 "uniform float FogHeightFade;\n"
1131 "vec3 FogVertex(vec3 surfacecolor)\n"
1132 "{\n"
1133 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1134 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1135 "       float fogfrac;\n"
1136 "#ifdef USEFOGHEIGHTTEXTURE\n"
1137 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1138 "       fogfrac = fogheightpixel.a;\n"
1139 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1140 "#else\n"
1141 "# ifdef USEFOGOUTSIDE\n"
1142 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1143 "# else\n"
1144 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1145 "# endif\n"
1146 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1147 "#endif\n"
1148 "}\n"
1149 "#endif\n"
1150 "\n"
1151 "#ifdef USEOFFSETMAPPING\n"
1152 "uniform float OffsetMapping_Scale;\n"
1153 "vec2 OffsetMapping(vec2 TexCoord)\n"
1154 "{\n"
1155 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1156 "       // 14 sample relief mapping: linear search and then binary search\n"
1157 "       // this basically steps forward a small amount repeatedly until it finds\n"
1158 "       // itself inside solid, then jitters forward and back using decreasing\n"
1159 "       // amounts to find the impact\n"
1160 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1161 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1162 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1163 "       vec3 RT = vec3(TexCoord, 1);\n"
1164 "       OffsetVector *= 0.1;\n"
1165 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1166 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1167 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1168 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1169 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1170 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1171 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1172 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1173 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1174 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1175 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1176 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1177 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1178 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1179 "       return RT.xy;\n"
1180 "#else\n"
1181 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1182 "       // this basically moves forward the full distance, and then backs up based\n"
1183 "       // on height of samples\n"
1184 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1185 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1186 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1187 "       TexCoord += OffsetVector;\n"
1188 "       OffsetVector *= 0.333;\n"
1189 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1190 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1191 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1192 "       return TexCoord;\n"
1193 "#endif\n"
1194 "}\n"
1195 "#endif // USEOFFSETMAPPING\n"
1196 "\n"
1197 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1198 "uniform sampler2D Texture_Attenuation;\n"
1199 "uniform samplerCube Texture_Cube;\n"
1200 "#endif\n"
1201 "\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1203 "\n"
1204 "#ifdef USESHADOWMAPRECT\n"
1205 "# ifdef USESHADOWSAMPLER\n"
1206 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1207 "# else\n"
1208 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1209 "# endif\n"
1210 "#endif\n"
1211 "\n"
1212 "#ifdef USESHADOWMAP2D\n"
1213 "# ifdef USESHADOWSAMPLER\n"
1214 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1215 "# else\n"
1216 "uniform sampler2D Texture_ShadowMap2D;\n"
1217 "# endif\n"
1218 "#endif\n"
1219 "\n"
1220 "#ifdef USESHADOWMAPVSDCT\n"
1221 "uniform samplerCube Texture_CubeProjection;\n"
1222 "#endif\n"
1223 "\n"
1224 "#ifdef USESHADOWMAPCUBE\n"
1225 "# ifdef USESHADOWSAMPLER\n"
1226 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1227 "# else\n"
1228 "uniform samplerCube Texture_ShadowMapCube;\n"
1229 "# endif\n"
1230 "#endif\n"
1231 "\n"
1232 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1233 "uniform vec2 ShadowMap_TextureScale;\n"
1234 "uniform vec4 ShadowMap_Parameters;\n"
1235 "#endif\n"
1236 "\n"
1237 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1238 "# ifdef USESHADOWMAPORTHO\n"
1239 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1240 "# else\n"
1241 "#  ifdef USESHADOWMAPVSDCT\n"
1242 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1243 "{\n"
1244 "       vec3 adir = abs(dir);\n"
1245 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1246 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1247 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1248 "}\n"
1249 "#  else\n"
1250 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1251 "{\n"
1252 "       vec3 adir = abs(dir);\n"
1253 "       float ma = adir.z;\n"
1254 "       vec4 proj = vec4(dir, 2.5);\n"
1255 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1256 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1257 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1258 "       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"
1259 "}\n"
1260 "#  endif\n"
1261 "# endif\n"
1262 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1263 "\n"
1264 "#ifdef USESHADOWMAPCUBE\n"
1265 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1266 "{\n"
1267 "       vec3 adir = abs(dir);\n"
1268 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1269 "}\n"
1270 "#endif\n"
1271 "\n"
1272 "# ifdef USESHADOWMAPRECT\n"
1273 "float ShadowMapCompare(vec3 dir)\n"
1274 "{\n"
1275 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1276 "       float f;\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "\n"
1279 "#    ifdef USESHADOWMAPPCF\n"
1280 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\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 = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1284 "#    endif\n"
1285 "\n"
1286 "#  else\n"
1287 "\n"
1288 "#    ifdef USESHADOWMAPPCF\n"
1289 "#      if USESHADOWMAPPCF > 1\n"
1290 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1291 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1292 "       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"
1293 "       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"
1294 "       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"
1295 "       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"
1296 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1297 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1298 "#      else\n"
1299 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1300 "       vec2 offset = fract(shadowmaptc.xy);\n"
1301 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1302 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1303 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1304 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1305 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1306 "#      endif\n"
1307 "#    else\n"
1308 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1309 "#    endif\n"
1310 "\n"
1311 "#  endif\n"
1312 "#  ifdef USESHADOWMAPORTHO\n"
1313 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1314 "#  else\n"
1315 "       return f;\n"
1316 "#  endif\n"
1317 "}\n"
1318 "# endif\n"
1319 "\n"
1320 "# ifdef USESHADOWMAP2D\n"
1321 "float ShadowMapCompare(vec3 dir)\n"
1322 "{\n"
1323 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1324 "       float f;\n"
1325 "\n"
1326 "#  ifdef USESHADOWSAMPLER\n"
1327 "#    ifdef USESHADOWMAPPCF\n"
1328 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1329 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1330 "       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"
1331 "#    else\n"
1332 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1333 "#    endif\n"
1334 "#  else\n"
1335 "#    ifdef USESHADOWMAPPCF\n"
1336 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1337 "#      ifdef GL_ARB_texture_gather\n"
1338 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1339 "#      else\n"
1340 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1341 "#      endif\n"
1342 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1343 "#      if USESHADOWMAPPCF > 1\n"
1344 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1345 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1346 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1347 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1348 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1349 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1350 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1351 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1352 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1353 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1354 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1355 "       locols.yz += group2.ab;\n"
1356 "       hicols.yz += group8.rg;\n"
1357 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1358 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1359 "                               mix(locols, hicols, offset.y);\n"
1360 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1361 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1362 "       f = dot(cols, vec4(1.0/25.0));\n"
1363 "#      else\n"
1364 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1365 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1366 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1367 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1368 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1369 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1370 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1371 "#      endif\n"
1372 "#     else\n"
1373 "#      ifdef GL_EXT_gpu_shader4\n"
1374 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1375 "#      else\n"
1376 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1377 "#      endif\n"
1378 "#      if USESHADOWMAPPCF > 1\n"
1379 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1380 "       center *= ShadowMap_TextureScale;\n"
1381 "       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"
1382 "       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"
1383 "       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"
1384 "       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"
1385 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1386 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1387 "#      else\n"
1388 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1389 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1390 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1391 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1392 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1393 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1394 "#      endif\n"
1395 "#     endif\n"
1396 "#    else\n"
1397 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1398 "#    endif\n"
1399 "#  endif\n"
1400 "#  ifdef USESHADOWMAPORTHO\n"
1401 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1402 "#  else\n"
1403 "       return f;\n"
1404 "#  endif\n"
1405 "}\n"
1406 "# endif\n"
1407 "\n"
1408 "# ifdef USESHADOWMAPCUBE\n"
1409 "float ShadowMapCompare(vec3 dir)\n"
1410 "{\n"
1411 "       // apply depth texture cubemap as light filter\n"
1412 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1413 "       float f;\n"
1414 "#  ifdef USESHADOWSAMPLER\n"
1415 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1416 "#  else\n"
1417 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1418 "#  endif\n"
1419 "       return f;\n"
1420 "}\n"
1421 "# endif\n"
1422 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1423 "#endif // FRAGMENT_SHADER\n"
1424 "\n"
1425 "\n"
1426 "\n"
1427 "\n"
1428 "#ifdef MODE_DEFERREDGEOMETRY\n"
1429 "#ifdef VERTEX_SHADER\n"
1430 "uniform mat4 TexMatrix;\n"
1431 "#ifdef USEVERTEXTEXTUREBLEND\n"
1432 "uniform mat4 BackgroundTexMatrix;\n"
1433 "#endif\n"
1434 "uniform mat4 ModelViewMatrix;\n"
1435 "void main(void)\n"
1436 "{\n"
1437 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1438 "#ifdef USEVERTEXTEXTUREBLEND\n"
1439 "       gl_FrontColor = gl_Color;\n"
1440 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1441 "#endif\n"
1442 "\n"
1443 "       // transform unnormalized eye direction into tangent space\n"
1444 "#ifdef USEOFFSETMAPPING\n"
1445 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1446 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1447 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1448 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1449 "#endif\n"
1450 "\n"
1451 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1452 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1453 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1454 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1455 "}\n"
1456 "#endif // VERTEX_SHADER\n"
1457 "\n"
1458 "#ifdef FRAGMENT_SHADER\n"
1459 "void main(void)\n"
1460 "{\n"
1461 "#ifdef USEOFFSETMAPPING\n"
1462 "       // apply offsetmapping\n"
1463 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1464 "#define TexCoord TexCoordOffset\n"
1465 "#endif\n"
1466 "\n"
1467 "#ifdef USEALPHAKILL\n"
1468 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1469 "               discard;\n"
1470 "#endif\n"
1471 "\n"
1472 "#ifdef USEVERTEXTEXTUREBLEND\n"
1473 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1474 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1475 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1476 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1477 "#endif\n"
1478 "\n"
1479 "#ifdef USEVERTEXTEXTUREBLEND\n"
1480 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1481 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1482 "#else\n"
1483 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1484 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1485 "#endif\n"
1486 "\n"
1487 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1488 "}\n"
1489 "#endif // FRAGMENT_SHADER\n"
1490 "#else // !MODE_DEFERREDGEOMETRY\n"
1491 "\n"
1492 "\n"
1493 "\n"
1494 "\n"
1495 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1496 "#ifdef VERTEX_SHADER\n"
1497 "uniform mat4 ModelViewMatrix;\n"
1498 "void main(void)\n"
1499 "{\n"
1500 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1501 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1502 "}\n"
1503 "#endif // VERTEX_SHADER\n"
1504 "\n"
1505 "#ifdef FRAGMENT_SHADER\n"
1506 "uniform mat4 ViewToLight;\n"
1507 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1508 "uniform vec2 ScreenToDepth;\n"
1509 "uniform myhalf3 DeferredColor_Ambient;\n"
1510 "uniform myhalf3 DeferredColor_Diffuse;\n"
1511 "#ifdef USESPECULAR\n"
1512 "uniform myhalf3 DeferredColor_Specular;\n"
1513 "uniform myhalf SpecularPower;\n"
1514 "#endif\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "void main(void)\n"
1517 "{\n"
1518 "       // calculate viewspace pixel position\n"
1519 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1520 "       vec3 position;\n"
1521 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1522 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1523 "       // decode viewspace pixel normal\n"
1524 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1525 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1526 "       // surfacenormal = pixel normal in viewspace\n"
1527 "       // LightVector = pixel to light in viewspace\n"
1528 "       // CubeVector = position in lightspace\n"
1529 "       // eyevector = pixel to view in viewspace\n"
1530 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1531 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1532 "#ifdef USEDIFFUSE\n"
1533 "       // calculate diffuse shading\n"
1534 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1535 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1536 "#endif\n"
1537 "#ifdef USESPECULAR\n"
1538 "       // calculate directional shading\n"
1539 "       vec3 eyevector = position * -1.0;\n"
1540 "#  ifdef USEEXACTSPECULARMATH\n"
1541 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1542 "#  else\n"
1543 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1544 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1545 "#  endif\n"
1546 "#endif\n"
1547 "\n"
1548 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1549 "       fade *= ShadowMapCompare(CubeVector);\n"
1550 "#endif\n"
1551 "\n"
1552 "#ifdef USEDIFFUSE\n"
1553 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1554 "#else\n"
1555 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1556 "#endif\n"
1557 "#ifdef USESPECULAR\n"
1558 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1559 "#else\n"
1560 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1561 "#endif\n"
1562 "\n"
1563 "# ifdef USECUBEFILTER\n"
1564 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1565 "       gl_FragData[0].rgb *= cubecolor;\n"
1566 "       gl_FragData[1].rgb *= cubecolor;\n"
1567 "# endif\n"
1568 "}\n"
1569 "#endif // FRAGMENT_SHADER\n"
1570 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "\n"
1575 "#ifdef VERTEX_SHADER\n"
1576 "uniform mat4 TexMatrix;\n"
1577 "#ifdef USEVERTEXTEXTUREBLEND\n"
1578 "uniform mat4 BackgroundTexMatrix;\n"
1579 "#endif\n"
1580 "#ifdef MODE_LIGHTSOURCE\n"
1581 "uniform mat4 ModelToLight;\n"
1582 "#endif\n"
1583 "#ifdef USESHADOWMAPORTHO\n"
1584 "uniform mat4 ShadowMapMatrix;\n"
1585 "#endif\n"
1586 "void main(void)\n"
1587 "{\n"
1588 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1589 "       gl_FrontColor = gl_Color;\n"
1590 "#endif\n"
1591 "       // copy the surface texcoord\n"
1592 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1593 "#ifdef USEVERTEXTEXTUREBLEND\n"
1594 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1595 "#endif\n"
1596 "#ifdef USELIGHTMAP\n"
1597 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1598 "#endif\n"
1599 "\n"
1600 "#ifdef MODE_LIGHTSOURCE\n"
1601 "       // transform vertex position into light attenuation/cubemap space\n"
1602 "       // (-1 to +1 across the light box)\n"
1603 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1604 "\n"
1605 "# ifdef USEDIFFUSE\n"
1606 "       // transform unnormalized light direction into tangent space\n"
1607 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1608 "       //  normalize it per pixel)\n"
1609 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1610 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1611 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1612 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1613 "# endif\n"
1614 "#endif\n"
1615 "\n"
1616 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1617 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1618 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1619 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1620 "#endif\n"
1621 "\n"
1622 "       // transform unnormalized eye direction into tangent space\n"
1623 "#ifdef USEEYEVECTOR\n"
1624 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1625 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1626 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1627 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1628 "#endif\n"
1629 "\n"
1630 "#ifdef USEFOG\n"
1631 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1632 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1633 "#endif\n"
1634 "\n"
1635 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1636 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1637 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1638 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1639 "#endif\n"
1640 "\n"
1641 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1642 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1643 "\n"
1644 "#ifdef USESHADOWMAPORTHO\n"
1645 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1646 "#endif\n"
1647 "\n"
1648 "#ifdef USEREFLECTION\n"
1649 "       ModelViewProjectionPosition = gl_Position;\n"
1650 "#endif\n"
1651 "}\n"
1652 "#endif // VERTEX_SHADER\n"
1653 "\n"
1654 "\n"
1655 "\n"
1656 "\n"
1657 "#ifdef FRAGMENT_SHADER\n"
1658 "#ifdef USEDEFERREDLIGHTMAP\n"
1659 "uniform myhalf2 PixelToScreenTexCoord;\n"
1660 "uniform myhalf3 DeferredMod_Diffuse;\n"
1661 "uniform myhalf3 DeferredMod_Specular;\n"
1662 "#endif\n"
1663 "uniform myhalf3 Color_Ambient;\n"
1664 "uniform myhalf3 Color_Diffuse;\n"
1665 "uniform myhalf3 Color_Specular;\n"
1666 "uniform myhalf SpecularPower;\n"
1667 "#ifdef USEGLOW\n"
1668 "uniform myhalf3 Color_Glow;\n"
1669 "#endif\n"
1670 "uniform myhalf Alpha;\n"
1671 "#ifdef USEREFLECTION\n"
1672 "uniform vec4 DistortScaleRefractReflect;\n"
1673 "uniform vec4 ScreenScaleRefractReflect;\n"
1674 "uniform vec4 ScreenCenterRefractReflect;\n"
1675 "uniform myhalf4 ReflectColor;\n"
1676 "#endif\n"
1677 "#ifdef USEREFLECTCUBE\n"
1678 "uniform mat4 ModelToReflectCube;\n"
1679 "uniform sampler2D Texture_ReflectMask;\n"
1680 "uniform samplerCube Texture_ReflectCube;\n"
1681 "#endif\n"
1682 "#ifdef MODE_LIGHTDIRECTION\n"
1683 "uniform myhalf3 LightColor;\n"
1684 "#endif\n"
1685 "#ifdef MODE_LIGHTSOURCE\n"
1686 "uniform myhalf3 LightColor;\n"
1687 "#endif\n"
1688 "void main(void)\n"
1689 "{\n"
1690 "#ifdef USEOFFSETMAPPING\n"
1691 "       // apply offsetmapping\n"
1692 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1693 "#define TexCoord TexCoordOffset\n"
1694 "#endif\n"
1695 "\n"
1696 "       // combine the diffuse textures (base, pants, shirt)\n"
1697 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1698 "#ifdef USEALPHAKILL\n"
1699 "       if (color.a < 0.5)\n"
1700 "               discard;\n"
1701 "#endif\n"
1702 "       color.a *= Alpha;\n"
1703 "#ifdef USECOLORMAPPING\n"
1704 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1705 "#endif\n"
1706 "#ifdef USEVERTEXTEXTUREBLEND\n"
1707 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1708 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1709 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1710 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1711 "       color.a = 1.0;\n"
1712 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1713 "#endif\n"
1714 "\n"
1715 "       // get the surface normal\n"
1716 "#ifdef USEVERTEXTEXTUREBLEND\n"
1717 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1718 "#else\n"
1719 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1720 "#endif\n"
1721 "\n"
1722 "       // get the material colors\n"
1723 "       myhalf3 diffusetex = color.rgb;\n"
1724 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1725 "# ifdef USEVERTEXTEXTUREBLEND\n"
1726 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1727 "# else\n"
1728 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1729 "# endif\n"
1730 "#endif\n"
1731 "\n"
1732 "#ifdef USEREFLECTCUBE\n"
1733 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1734 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1735 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1736 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1737 "#endif\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "\n"
1742 "#ifdef MODE_LIGHTSOURCE\n"
1743 "       // light source\n"
1744 "#ifdef USEDIFFUSE\n"
1745 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1746 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1747 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1748 "#ifdef USESPECULAR\n"
1749 "#ifdef USEEXACTSPECULARMATH\n"
1750 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1751 "#else\n"
1752 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1753 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1754 "#endif\n"
1755 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1756 "#endif\n"
1757 "#else\n"
1758 "       color.rgb = diffusetex * Color_Ambient;\n"
1759 "#endif\n"
1760 "       color.rgb *= LightColor;\n"
1761 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1762 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1763 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1764 "#endif\n"
1765 "# ifdef USECUBEFILTER\n"
1766 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1767 "# endif\n"
1768 "#endif // MODE_LIGHTSOURCE\n"
1769 "\n"
1770 "\n"
1771 "\n"
1772 "\n"
1773 "#ifdef MODE_LIGHTDIRECTION\n"
1774 "#define SHADING\n"
1775 "#ifdef USEDIFFUSE\n"
1776 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1777 "#endif\n"
1778 "#define lightcolor LightColor\n"
1779 "#endif // MODE_LIGHTDIRECTION\n"
1780 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1781 "#define SHADING\n"
1782 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1783 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1784 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1785 "       // convert modelspace light vector to tangentspace\n"
1786 "       myhalf3 lightnormal;\n"
1787 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1788 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1789 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1790 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1791 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1792 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1793 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1794 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1795 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1796 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1797 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1798 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1799 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1800 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1801 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1802 "#define SHADING\n"
1803 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1804 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1805 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1806 "#endif\n"
1807 "\n"
1808 "\n"
1809 "\n"
1810 "\n"
1811 "#ifdef MODE_LIGHTMAP\n"
1812 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1813 "#endif // MODE_LIGHTMAP\n"
1814 "#ifdef MODE_VERTEXCOLOR\n"
1815 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1816 "#endif // MODE_VERTEXCOLOR\n"
1817 "#ifdef MODE_FLATCOLOR\n"
1818 "       color.rgb = diffusetex * Color_Ambient;\n"
1819 "#endif // MODE_FLATCOLOR\n"
1820 "\n"
1821 "\n"
1822 "\n"
1823 "\n"
1824 "#ifdef SHADING\n"
1825 "# ifdef USEDIFFUSE\n"
1826 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1827 "#  ifdef USESPECULAR\n"
1828 "#   ifdef USEEXACTSPECULARMATH\n"
1829 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1830 "#   else\n"
1831 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1832 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1833 "#   endif\n"
1834 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1835 "#  else\n"
1836 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1837 "#  endif\n"
1838 "# else\n"
1839 "       color.rgb = diffusetex * Color_Ambient;\n"
1840 "# endif\n"
1841 "#endif\n"
1842 "\n"
1843 "#ifdef USESHADOWMAPORTHO\n"
1844 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1845 "#endif\n"
1846 "\n"
1847 "#ifdef USEDEFERREDLIGHTMAP\n"
1848 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1849 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1850 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1851 "#endif\n"
1852 "\n"
1853 "#ifdef USEGLOW\n"
1854 "#ifdef USEVERTEXTEXTUREBLEND\n"
1855 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1856 "#else\n"
1857 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1858 "#endif\n"
1859 "#endif\n"
1860 "\n"
1861 "#ifdef USEFOG\n"
1862 "       color.rgb = FogVertex(color.rgb);\n"
1863 "#endif\n"
1864 "\n"
1865 "       // 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"
1866 "#ifdef USEREFLECTION\n"
1867 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1868 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1869 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1870 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1871 "       // FIXME temporary hack to detect the case that the reflection\n"
1872 "       // gets blackened at edges due to leaving the area that contains actual\n"
1873 "       // content.\n"
1874 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1875 "       // 'appening.\n"
1876 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1877 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1878 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1879 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1880 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1881 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1882 "#endif\n"
1883 "\n"
1884 "       gl_FragColor = vec4(color);\n"
1885 "}\n"
1886 "#endif // FRAGMENT_SHADER\n"
1887 "\n"
1888 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1889 "#endif // !MODE_DEFERREDGEOMETRY\n"
1890 "#endif // !MODE_WATER\n"
1891 "#endif // !MODE_REFRACTION\n"
1892 "#endif // !MODE_BLOOMBLUR\n"
1893 "#endif // !MODE_GENERIC\n"
1894 "#endif // !MODE_POSTPROCESS\n"
1895 "#endif // !MODE_SHOWDEPTH\n"
1896 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1897 ;
1898
1899 /*
1900 =========================================================================================================================================================
1901
1902
1903
1904 =========================================================================================================================================================
1905
1906
1907
1908 =========================================================================================================================================================
1909
1910
1911
1912 =========================================================================================================================================================
1913
1914
1915
1916 =========================================================================================================================================================
1917
1918
1919
1920 =========================================================================================================================================================
1921
1922
1923
1924 =========================================================================================================================================================
1925 */
1926
1927 const char *builtincgshaderstring =
1928 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1929 "// written by Forest 'LordHavoc' Hale\n"
1930 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1931 "\n"
1932 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1933 "#if defined(USEREFLECTION)\n"
1934 "#undef USESHADOWMAPORTHO\n"
1935 "#endif\n"
1936 "\n"
1937 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1938 "# define USEFOG\n"
1939 "#endif\n"
1940 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1941 "#define USELIGHTMAP\n"
1942 "#endif\n"
1943 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1944 "#define USEEYEVECTOR\n"
1945 "#endif\n"
1946 "\n"
1947 "#ifdef FRAGMENT_SHADER\n"
1948 "#ifdef HLSL\n"
1949 "//#undef USESHADOWMAPPCF\n"
1950 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1951 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1952 "#else\n"
1953 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1954 "#endif\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1958 "#ifdef VERTEX_SHADER\n"
1959 "void main\n"
1960 "(\n"
1961 "float4 gl_Vertex : POSITION,\n"
1962 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1963 "out float4 gl_Position : POSITION,\n"
1964 "out float Depth : TEXCOORD0\n"
1965 ")\n"
1966 "{\n"
1967 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1968 "       Depth = gl_Position.z;\n"
1969 "}\n"
1970 "#endif\n"
1971 "\n"
1972 "#ifdef FRAGMENT_SHADER\n"
1973 "void main\n"
1974 "(\n"
1975 "float Depth : TEXCOORD0,\n"
1976 "out float4 gl_FragColor : COLOR\n"
1977 ")\n"
1978 "{\n"
1979 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1980 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1981 "       temp.yz -= floor(temp.yz);\n"
1982 "       gl_FragColor = float4(temp,0);\n"
1983 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1984 "}\n"
1985 "#endif\n"
1986 "#else // !MODE_DEPTH_ORSHADOW\n"
1987 "\n"
1988 "\n"
1989 "\n"
1990 "\n"
1991 "#ifdef MODE_SHOWDEPTH\n"
1992 "#ifdef VERTEX_SHADER\n"
1993 "void main\n"
1994 "(\n"
1995 "float4 gl_Vertex : POSITION,\n"
1996 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1997 "out float4 gl_Position : POSITION,\n"
1998 "out float4 gl_FrontColor : COLOR0\n"
1999 ")\n"
2000 "{\n"
2001 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2002 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
2003 "}\n"
2004 "#endif\n"
2005 "\n"
2006 "#ifdef FRAGMENT_SHADER\n"
2007 "void main\n"
2008 "(\n"
2009 "float4 gl_FrontColor : COLOR0,\n"
2010 "out float4 gl_FragColor : COLOR\n"
2011 ")\n"
2012 "{\n"
2013 "       gl_FragColor = gl_FrontColor;\n"
2014 "}\n"
2015 "#endif\n"
2016 "#else // !MODE_SHOWDEPTH\n"
2017 "\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "#ifdef MODE_POSTPROCESS\n"
2022 "\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "void main\n"
2025 "(\n"
2026 "float4 gl_Vertex : POSITION,\n"
2027 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2028 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2029 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2030 "out float4 gl_Position : POSITION,\n"
2031 "out float2 TexCoord1 : TEXCOORD0,\n"
2032 "out float2 TexCoord2 : TEXCOORD1\n"
2033 ")\n"
2034 "{\n"
2035 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2036 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2037 "#ifdef USEBLOOM\n"
2038 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
2039 "#endif\n"
2040 "}\n"
2041 "#endif\n"
2042 "\n"
2043 "#ifdef FRAGMENT_SHADER\n"
2044 "void main\n"
2045 "(\n"
2046 "float2 TexCoord1 : TEXCOORD0,\n"
2047 "float2 TexCoord2 : TEXCOORD1,\n"
2048 "uniform sampler Texture_First : register(s0),\n"
2049 "#ifdef USEBLOOM\n"
2050 "uniform sampler Texture_Second : register(s1),\n"
2051 "#endif\n"
2052 "#ifdef USEGAMMARAMPS\n"
2053 "uniform sampler Texture_GammaRamps : register(s2),\n"
2054 "#endif\n"
2055 "#ifdef USESATURATION\n"
2056 "uniform float Saturation : register(c30),\n"
2057 "#endif\n"
2058 "#ifdef USEVIEWTINT\n"
2059 "uniform float4 ViewTintColor : register(c41),\n"
2060 "#endif\n"
2061 "uniform float4 UserVec1 : register(c37),\n"
2062 "uniform float4 UserVec2 : register(c38),\n"
2063 "uniform float4 UserVec3 : register(c39),\n"
2064 "uniform float4 UserVec4 : register(c40),\n"
2065 "uniform float ClientTime : register(c2),\n"
2066 "uniform float2 PixelSize : register(c25),\n"
2067 "uniform float4 BloomColorSubtract : register(c43),\n"
2068 "out float4 gl_FragColor : COLOR\n"
2069 ")\n"
2070 "{\n"
2071 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2072 "#ifdef USEBLOOM\n"
2073 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2074 "#endif\n"
2075 "#ifdef USEVIEWTINT\n"
2076 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2077 "#endif\n"
2078 "\n"
2079 "#ifdef USEPOSTPROCESSING\n"
2080 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2081 "// 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"
2082 "       float sobel = 1.0;\n"
2083 "       // float2 ts = textureSize(Texture_First, 0);\n"
2084 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2085 "       float2 px = PixelSize;\n"
2086 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2087 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2088 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2089 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2090 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2091 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2092 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2093 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2094 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2095 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2096 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2097 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2098 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2099 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2100 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2101 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2102 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2103 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2104 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2105 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2106 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2107 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2108 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2109 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2110 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2111 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2112 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2113 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2114 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2115 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2116 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2117 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef USESATURATION\n"
2121 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2122 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2123 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2124 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2125 "#endif\n"
2126 "\n"
2127 "#ifdef USEGAMMARAMPS\n"
2128 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2129 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2130 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2131 "#endif\n"
2132 "}\n"
2133 "#endif\n"
2134 "#else // !MODE_POSTPROCESS\n"
2135 "\n"
2136 "\n"
2137 "\n"
2138 "\n"
2139 "#ifdef MODE_GENERIC\n"
2140 "#ifdef VERTEX_SHADER\n"
2141 "void main\n"
2142 "(\n"
2143 "float4 gl_Vertex : POSITION,\n"
2144 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2145 "float4 gl_Color : COLOR0,\n"
2146 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2147 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2148 "out float4 gl_Position : POSITION,\n"
2149 "out float4 gl_FrontColor : COLOR,\n"
2150 "out float2 TexCoord1 : TEXCOORD0,\n"
2151 "out float2 TexCoord2 : TEXCOORD1\n"
2152 ")\n"
2153 "{\n"
2154 "#ifdef HLSL\n"
2155 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2156 "#else\n"
2157 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2158 "#endif\n"
2159 "#ifdef USEDIFFUSE\n"
2160 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2161 "#endif\n"
2162 "#ifdef USESPECULAR\n"
2163 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2164 "#endif\n"
2165 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2166 "}\n"
2167 "#endif\n"
2168 "\n"
2169 "#ifdef FRAGMENT_SHADER\n"
2170 "\n"
2171 "void main\n"
2172 "(\n"
2173 "float4 gl_FrontColor : COLOR0,\n"
2174 "float2 TexCoord1 : TEXCOORD0,\n"
2175 "float2 TexCoord2 : TEXCOORD1,\n"
2176 "#ifdef USEDIFFUSE\n"
2177 "uniform sampler Texture_First : register(s0),\n"
2178 "#endif\n"
2179 "#ifdef USESPECULAR\n"
2180 "uniform sampler Texture_Second : register(s1),\n"
2181 "#endif\n"
2182 "out float4 gl_FragColor : COLOR\n"
2183 ")\n"
2184 "{\n"
2185 "       gl_FragColor = gl_FrontColor;\n"
2186 "#ifdef USEDIFFUSE\n"
2187 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2188 "#endif\n"
2189 "\n"
2190 "#ifdef USESPECULAR\n"
2191 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2192 "# ifdef USECOLORMAPPING\n"
2193 "       gl_FragColor *= tex2;\n"
2194 "# endif\n"
2195 "# ifdef USEGLOW\n"
2196 "       gl_FragColor += tex2;\n"
2197 "# endif\n"
2198 "# ifdef USEVERTEXTEXTUREBLEND\n"
2199 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2200 "# endif\n"
2201 "#endif\n"
2202 "}\n"
2203 "#endif\n"
2204 "#else // !MODE_GENERIC\n"
2205 "\n"
2206 "\n"
2207 "\n"
2208 "\n"
2209 "#ifdef MODE_BLOOMBLUR\n"
2210 "#ifdef VERTEX_SHADER\n"
2211 "void main\n"
2212 "(\n"
2213 "float4 gl_Vertex : POSITION,\n"
2214 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2215 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2216 "out float4 gl_Position : POSITION,\n"
2217 "out float2 TexCoord : TEXCOORD0\n"
2218 ")\n"
2219 "{\n"
2220 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2221 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2222 "}\n"
2223 "#endif\n"
2224 "\n"
2225 "#ifdef FRAGMENT_SHADER\n"
2226 "\n"
2227 "void main\n"
2228 "(\n"
2229 "float2 TexCoord : TEXCOORD0,\n"
2230 "uniform sampler Texture_First : register(s0),\n"
2231 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2232 "out float4 gl_FragColor : COLOR\n"
2233 ")\n"
2234 "{\n"
2235 "       int i;\n"
2236 "       float2 tc = TexCoord;\n"
2237 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2238 "       tc += BloomBlur_Parameters.xy;\n"
2239 "       for (i = 1;i < SAMPLES;i++)\n"
2240 "       {\n"
2241 "               color += tex2D(Texture_First, tc).rgb;\n"
2242 "               tc += BloomBlur_Parameters.xy;\n"
2243 "       }\n"
2244 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2245 "}\n"
2246 "#endif\n"
2247 "#else // !MODE_BLOOMBLUR\n"
2248 "#ifdef MODE_REFRACTION\n"
2249 "#ifdef VERTEX_SHADER\n"
2250 "void main\n"
2251 "(\n"
2252 "float4 gl_Vertex : POSITION,\n"
2253 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2254 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2255 "uniform float4x4 TexMatrix : register(c0),\n"
2256 "uniform float3 EyePosition : register(c24),\n"
2257 "out float4 gl_Position : POSITION,\n"
2258 "out float2 TexCoord : TEXCOORD0,\n"
2259 "out float3 EyeVector : TEXCOORD1,\n"
2260 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2261 ")\n"
2262 "{\n"
2263 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2264 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2265 "       ModelViewProjectionPosition = gl_Position;\n"
2266 "}\n"
2267 "#endif\n"
2268 "\n"
2269 "#ifdef FRAGMENT_SHADER\n"
2270 "void main\n"
2271 "(\n"
2272 "float2 TexCoord : TEXCOORD0,\n"
2273 "float3 EyeVector : TEXCOORD1,\n"
2274 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2275 "uniform sampler Texture_Normal : register(s0),\n"
2276 "uniform sampler Texture_Refraction : register(s3),\n"
2277 "uniform sampler Texture_Reflection : register(s7),\n"
2278 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2279 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2280 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2281 "uniform float4 RefractColor : register(c29),\n"
2282 "out float4 gl_FragColor : COLOR\n"
2283 ")\n"
2284 "{\n"
2285 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2286 "       //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"
2287 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2288 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2289 "       // FIXME temporary hack to detect the case that the reflection\n"
2290 "       // gets blackened at edges due to leaving the area that contains actual\n"
2291 "       // content.\n"
2292 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2293 "       // 'appening.\n"
2294 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2295 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2296 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2297 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2298 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2299 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2300 "}\n"
2301 "#endif\n"
2302 "#else // !MODE_REFRACTION\n"
2303 "\n"
2304 "\n"
2305 "\n"
2306 "\n"
2307 "#ifdef MODE_WATER\n"
2308 "#ifdef VERTEX_SHADER\n"
2309 "\n"
2310 "void main\n"
2311 "(\n"
2312 "float4 gl_Vertex : POSITION,\n"
2313 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2314 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2315 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2316 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2317 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2318 "uniform float4x4 TexMatrix : register(c0),\n"
2319 "uniform float3 EyePosition : register(c24),\n"
2320 "out float4 gl_Position : POSITION,\n"
2321 "out float2 TexCoord : TEXCOORD0,\n"
2322 "out float3 EyeVector : TEXCOORD1,\n"
2323 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2324 ")\n"
2325 "{\n"
2326 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2327 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2328 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2329 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2330 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2331 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2332 "       ModelViewProjectionPosition = gl_Position;\n"
2333 "}\n"
2334 "#endif\n"
2335 "\n"
2336 "#ifdef FRAGMENT_SHADER\n"
2337 "void main\n"
2338 "(\n"
2339 "float2 TexCoord : TEXCOORD0,\n"
2340 "float3 EyeVector : TEXCOORD1,\n"
2341 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2342 "uniform sampler Texture_Normal : register(s0),\n"
2343 "uniform sampler Texture_Refraction : register(s3),\n"
2344 "uniform sampler Texture_Reflection : register(s7),\n"
2345 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2346 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2347 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2348 "uniform float4 RefractColor : register(c29),\n"
2349 "uniform float4 ReflectColor : register(c26),\n"
2350 "uniform float ReflectFactor : register(c27),\n"
2351 "uniform float ReflectOffset : register(c28),\n"
2352 "out float4 gl_FragColor : COLOR\n"
2353 ")\n"
2354 "{\n"
2355 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2356 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2357 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2358 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2359 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xyxy * DistortScaleRefractReflect;\n"
2360 "       // FIXME temporary hack to detect the case that the reflection\n"
2361 "       // gets blackened at edges due to leaving the area that contains actual\n"
2362 "       // content.\n"
2363 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2364 "       // 'appening.\n"
2365 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2366 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2367 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2368 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2369 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2370 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2371 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2372 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2373 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2374 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2375 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2376 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2377 "}\n"
2378 "#endif\n"
2379 "#else // !MODE_WATER\n"
2380 "\n"
2381 "\n"
2382 "\n"
2383 "\n"
2384 "// 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"
2385 "\n"
2386 "// fragment shader specific:\n"
2387 "#ifdef FRAGMENT_SHADER\n"
2388 "\n"
2389 "#ifdef USEFOG\n"
2390 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2391 "{\n"
2392 "       float fogfrac;\n"
2393 "#ifdef USEFOGHEIGHTTEXTURE\n"
2394 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2395 "       fogfrac = fogheightpixel.a;\n"
2396 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2397 "#else\n"
2398 "# ifdef USEFOGOUTSIDE\n"
2399 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2400 "# else\n"
2401 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2402 "# endif\n"
2403 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2404 "#endif\n"
2405 "}\n"
2406 "#endif\n"
2407 "\n"
2408 "#ifdef USEOFFSETMAPPING\n"
2409 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2410 "{\n"
2411 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2412 "       // 14 sample relief mapping: linear search and then binary search\n"
2413 "       // this basically steps forward a small amount repeatedly until it finds\n"
2414 "       // itself inside solid, then jitters forward and back using decreasing\n"
2415 "       // amounts to find the impact\n"
2416 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2417 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2418 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2419 "       float3 RT = float3(TexCoord, 1);\n"
2420 "       OffsetVector *= 0.1;\n"
2421 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2422 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2423 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2424 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2425 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2426 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2427 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2428 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2429 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2430 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2431 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2432 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2433 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2434 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2435 "       return RT.xy;\n"
2436 "#else\n"
2437 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2438 "       // this basically moves forward the full distance, and then backs up based\n"
2439 "       // on height of samples\n"
2440 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2441 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2442 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2443 "       TexCoord += OffsetVector;\n"
2444 "       OffsetVector *= 0.333;\n"
2445 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2446 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2447 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2448 "       return TexCoord;\n"
2449 "#endif\n"
2450 "}\n"
2451 "#endif // USEOFFSETMAPPING\n"
2452 "\n"
2453 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2454 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2455 "# ifdef USESHADOWMAPORTHO\n"
2456 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2457 "# else\n"
2458 "#  ifdef USESHADOWMAPVSDCT\n"
2459 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2460 "{\n"
2461 "       float3 adir = abs(dir);\n"
2462 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2463 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2464 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2465 "}\n"
2466 "#  else\n"
2467 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2468 "{\n"
2469 "       float3 adir = abs(dir);\n"
2470 "       float ma = adir.z;\n"
2471 "       float4 proj = float4(dir, 2.5);\n"
2472 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2473 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2474 "#ifdef HLSL\n"
2475 "       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"
2476 "#else\n"
2477 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2478 "       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"
2479 "#endif\n"
2480 "}\n"
2481 "#  endif\n"
2482 "# endif\n"
2483 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2484 "\n"
2485 "#ifdef USESHADOWMAPCUBE\n"
2486 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2487 "{\n"
2488 "       float3 adir = abs(dir);\n"
2489 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2490 "}\n"
2491 "#endif\n"
2492 "\n"
2493 "# ifdef USESHADOWMAPRECT\n"
2494 "#ifdef USESHADOWMAPVSDCT\n"
2495 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2496 "#else\n"
2497 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2498 "#endif\n"
2499 "{\n"
2500 "#ifdef USESHADOWMAPVSDCT\n"
2501 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2502 "#else\n"
2503 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2504 "#endif\n"
2505 "       float f;\n"
2506 "#  ifdef USESHADOWSAMPLER\n"
2507 "\n"
2508 "#    ifdef USESHADOWMAPPCF\n"
2509 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2510 "       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"
2511 "#    else\n"
2512 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2513 "#    endif\n"
2514 "\n"
2515 "#  else\n"
2516 "\n"
2517 "#    ifdef USESHADOWMAPPCF\n"
2518 "#      if USESHADOWMAPPCF > 1\n"
2519 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2520 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2521 "       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"
2522 "       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"
2523 "       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"
2524 "       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"
2525 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2526 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2529 "       float2 offset = frac(shadowmaptc.xy);\n"
2530 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2531 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2532 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2533 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2534 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2535 "#      endif\n"
2536 "#    else\n"
2537 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2538 "#    endif\n"
2539 "\n"
2540 "#  endif\n"
2541 "#  ifdef USESHADOWMAPORTHO\n"
2542 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2543 "#  else\n"
2544 "       return f;\n"
2545 "#  endif\n"
2546 "}\n"
2547 "# endif\n"
2548 "\n"
2549 "# ifdef USESHADOWMAP2D\n"
2550 "#ifdef USESHADOWMAPVSDCT\n"
2551 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2552 "#else\n"
2553 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2554 "#endif\n"
2555 "{\n"
2556 "#ifdef USESHADOWMAPVSDCT\n"
2557 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2558 "#else\n"
2559 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2560 "#endif\n"
2561 "       float f;\n"
2562 "\n"
2563 "#  ifdef USESHADOWSAMPLER\n"
2564 "#    ifdef USESHADOWMAPPCF\n"
2565 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2566 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2567 "       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"
2568 "#    else\n"
2569 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2570 "#    endif\n"
2571 "#  else\n"
2572 "#    ifdef USESHADOWMAPPCF\n"
2573 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2574 "#      ifdef GL_ARB_texture_gather\n"
2575 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2576 "#      else\n"
2577 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2578 "#      endif\n"
2579 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2580 "#      if USESHADOWMAPPCF > 1\n"
2581 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2582 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2583 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2584 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2585 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2586 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2587 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2588 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2589 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2590 "       float4 locols = float4(group1.ab, group3.ab);\n"
2591 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2592 "       locols.yz += group2.ab;\n"
2593 "       hicols.yz += group8.rg;\n"
2594 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2595 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2596 "                               lerp(locols, hicols, offset.y);\n"
2597 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2598 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2599 "       f = dot(cols, float4(1.0/25.0));\n"
2600 "#      else\n"
2601 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2602 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2603 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2604 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2605 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2606 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2607 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2608 "#      endif\n"
2609 "#     else\n"
2610 "#      ifdef GL_EXT_gpu_shader4\n"
2611 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2612 "#      else\n"
2613 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2614 "#      endif\n"
2615 "#      if USESHADOWMAPPCF > 1\n"
2616 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2617 "       center *= ShadowMap_TextureScale;\n"
2618 "       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"
2619 "       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"
2620 "       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"
2621 "       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"
2622 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2623 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2624 "#      else\n"
2625 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2626 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2627 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2628 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2629 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2630 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2631 "#      endif\n"
2632 "#     endif\n"
2633 "#    else\n"
2634 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2635 "#    endif\n"
2636 "#  endif\n"
2637 "#  ifdef USESHADOWMAPORTHO\n"
2638 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2639 "#  else\n"
2640 "       return f;\n"
2641 "#  endif\n"
2642 "}\n"
2643 "# endif\n"
2644 "\n"
2645 "# ifdef USESHADOWMAPCUBE\n"
2646 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2647 "{\n"
2648 "       // apply depth texture cubemap as light filter\n"
2649 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2650 "       float f;\n"
2651 "#  ifdef USESHADOWSAMPLER\n"
2652 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2653 "#  else\n"
2654 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2655 "#  endif\n"
2656 "       return f;\n"
2657 "}\n"
2658 "# endif\n"
2659 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2660 "#endif // FRAGMENT_SHADER\n"
2661 "\n"
2662 "\n"
2663 "\n"
2664 "\n"
2665 "#ifdef MODE_DEFERREDGEOMETRY\n"
2666 "#ifdef VERTEX_SHADER\n"
2667 "void main\n"
2668 "(\n"
2669 "float4 gl_Vertex : POSITION,\n"
2670 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2671 "#ifdef USEVERTEXTEXTUREBLEND\n"
2672 "float4 gl_Color : COLOR0,\n"
2673 "#endif\n"
2674 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2675 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2676 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2677 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2678 "uniform float4x4 TexMatrix : register(c0),\n"
2679 "#ifdef USEVERTEXTEXTUREBLEND\n"
2680 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2681 "#endif\n"
2682 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2683 "#ifdef USEOFFSETMAPPING\n"
2684 "uniform float3 EyePosition : register(c24),\n"
2685 "#endif\n"
2686 "out float4 gl_Position : POSITION,\n"
2687 "out float4 gl_FrontColor : COLOR,\n"
2688 "out float4 TexCoordBoth : TEXCOORD0,\n"
2689 "#ifdef USEOFFSETMAPPING\n"
2690 "out float3 EyeVector : TEXCOORD2,\n"
2691 "#endif\n"
2692 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2693 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2694 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2695 ")\n"
2696 "{\n"
2697 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2698 "#ifdef USEVERTEXTEXTUREBLEND\n"
2699 "#ifdef HLSL\n"
2700 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2701 "#else\n"
2702 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2703 "#endif\n"
2704 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2705 "#endif\n"
2706 "\n"
2707 "       // transform unnormalized eye direction into tangent space\n"
2708 "#ifdef USEOFFSETMAPPING\n"
2709 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2710 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2711 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2712 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2713 "#endif\n"
2714 "\n"
2715 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2716 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2717 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2718 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2719 "}\n"
2720 "#endif // VERTEX_SHADER\n"
2721 "\n"
2722 "#ifdef FRAGMENT_SHADER\n"
2723 "void main\n"
2724 "(\n"
2725 "float4 TexCoordBoth : TEXCOORD0,\n"
2726 "float3 EyeVector : TEXCOORD2,\n"
2727 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2728 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2729 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2730 "uniform sampler Texture_Normal : register(s0),\n"
2731 "#ifdef USEALPHAKILL\n"
2732 "uniform sampler Texture_Color : register(s1),\n"
2733 "#endif\n"
2734 "uniform sampler Texture_Gloss : register(s2),\n"
2735 "#ifdef USEVERTEXTEXTUREBLEND\n"
2736 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2737 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2738 "#endif\n"
2739 "#ifdef USEOFFSETMAPPING\n"
2740 "uniform float OffsetMapping_Scale : register(c24),\n"
2741 "#endif\n"
2742 "uniform half SpecularPower : register(c36),\n"
2743 "out float4 gl_FragColor : COLOR\n"
2744 ")\n"
2745 "{\n"
2746 "       float2 TexCoord = TexCoordBoth.xy;\n"
2747 "#ifdef USEOFFSETMAPPING\n"
2748 "       // apply offsetmapping\n"
2749 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2750 "#define TexCoord TexCoordOffset\n"
2751 "#endif\n"
2752 "\n"
2753 "#ifdef USEALPHAKILL\n"
2754 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2755 "               discard;\n"
2756 "#endif\n"
2757 "\n"
2758 "#ifdef USEVERTEXTEXTUREBLEND\n"
2759 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2760 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2761 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2762 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2763 "#endif\n"
2764 "\n"
2765 "#ifdef USEVERTEXTEXTUREBLEND\n"
2766 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2767 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2768 "#else\n"
2769 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2770 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2771 "#endif\n"
2772 "\n"
2773 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2774 "}\n"
2775 "#endif // FRAGMENT_SHADER\n"
2776 "#else // !MODE_DEFERREDGEOMETRY\n"
2777 "\n"
2778 "\n"
2779 "\n"
2780 "\n"
2781 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2782 "#ifdef VERTEX_SHADER\n"
2783 "void main\n"
2784 "(\n"
2785 "float4 gl_Vertex : POSITION,\n"
2786 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2787 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2788 "out float4 gl_Position : POSITION,\n"
2789 "out float4 ModelViewPosition : TEXCOORD0\n"
2790 ")\n"
2791 "{\n"
2792 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2793 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2794 "}\n"
2795 "#endif // VERTEX_SHADER\n"
2796 "\n"
2797 "#ifdef FRAGMENT_SHADER\n"
2798 "void main\n"
2799 "(\n"
2800 "#ifdef HLSL\n"
2801 "float2 Pixel : VPOS,\n"
2802 "#else\n"
2803 "float2 Pixel : WPOS,\n"
2804 "#endif\n"
2805 "float4 ModelViewPosition : TEXCOORD0,\n"
2806 "uniform float4x4 ViewToLight : register(c44),\n"
2807 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2808 "uniform float3 LightPosition : register(c23),\n"
2809 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2810 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2811 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2812 "#ifdef USESPECULAR\n"
2813 "uniform half3 DeferredColor_Specular : register(c11),\n"
2814 "uniform half SpecularPower : register(c36),\n"
2815 "#endif\n"
2816 "uniform sampler Texture_Attenuation : register(s9),\n"
2817 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2818 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2819 "\n"
2820 "#ifdef USECUBEFILTER\n"
2821 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2822 "#endif\n"
2823 "\n"
2824 "#ifdef USESHADOWMAPRECT\n"
2825 "# ifdef USESHADOWSAMPLER\n"
2826 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2827 "# else\n"
2828 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2829 "# endif\n"
2830 "#endif\n"
2831 "\n"
2832 "#ifdef USESHADOWMAP2D\n"
2833 "# ifdef USESHADOWSAMPLER\n"
2834 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2835 "# else\n"
2836 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2837 "# endif\n"
2838 "#endif\n"
2839 "\n"
2840 "#ifdef USESHADOWMAPVSDCT\n"
2841 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2842 "#endif\n"
2843 "\n"
2844 "#ifdef USESHADOWMAPCUBE\n"
2845 "# ifdef USESHADOWSAMPLER\n"
2846 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2847 "# else\n"
2848 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2849 "# endif\n"
2850 "#endif\n"
2851 "\n"
2852 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2853 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2854 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2855 "#endif\n"
2856 "\n"
2857 "out float4 gl_FragData0 : COLOR0,\n"
2858 "out float4 gl_FragData1 : COLOR1\n"
2859 ")\n"
2860 "{\n"
2861 "       // calculate viewspace pixel position\n"
2862 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2863 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2864 "       float3 position;\n"
2865 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2866 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2867 "       // decode viewspace pixel normal\n"
2868 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2869 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2870 "       // surfacenormal = pixel normal in viewspace\n"
2871 "       // LightVector = pixel to light in viewspace\n"
2872 "       // CubeVector = position in lightspace\n"
2873 "       // eyevector = pixel to view in viewspace\n"
2874 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2875 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2876 "#ifdef USEDIFFUSE\n"
2877 "       // calculate diffuse shading\n"
2878 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2879 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2880 "#endif\n"
2881 "#ifdef USESPECULAR\n"
2882 "       // calculate directional shading\n"
2883 "       float3 eyevector = position * -1.0;\n"
2884 "#  ifdef USEEXACTSPECULARMATH\n"
2885 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2886 "#  else\n"
2887 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2888 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2889 "#  endif\n"
2890 "#endif\n"
2891 "\n"
2892 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2893 "       fade *= ShadowMapCompare(CubeVector,\n"
2894 "# if defined(USESHADOWMAP2D)\n"
2895 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2896 "# endif\n"
2897 "# if defined(USESHADOWMAPRECT)\n"
2898 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2899 "# endif\n"
2900 "# if defined(USESHADOWMAPCUBE)\n"
2901 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2902 "# endif\n"
2903 "\n"
2904 "#ifdef USESHADOWMAPVSDCT\n"
2905 ", Texture_CubeProjection\n"
2906 "#endif\n"
2907 "       );\n"
2908 "#endif\n"
2909 "\n"
2910 "#ifdef USEDIFFUSE\n"
2911 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2912 "#else\n"
2913 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2914 "#endif\n"
2915 "#ifdef USESPECULAR\n"
2916 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2917 "#else\n"
2918 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2919 "#endif\n"
2920 "\n"
2921 "# ifdef USECUBEFILTER\n"
2922 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2923 "       gl_FragData0.rgb *= cubecolor;\n"
2924 "       gl_FragData1.rgb *= cubecolor;\n"
2925 "# endif\n"
2926 "}\n"
2927 "#endif // FRAGMENT_SHADER\n"
2928 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2929 "\n"
2930 "\n"
2931 "\n"
2932 "\n"
2933 "#ifdef VERTEX_SHADER\n"
2934 "void main\n"
2935 "(\n"
2936 "float4 gl_Vertex : POSITION,\n"
2937 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2938 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2939 "float4 gl_Color : COLOR0,\n"
2940 "#endif\n"
2941 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2942 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2943 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2944 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2945 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2946 "\n"
2947 "uniform float3 EyePosition : register(c24),\n"
2948 "uniform float4x4 TexMatrix : register(c0),\n"
2949 "#ifdef USEVERTEXTEXTUREBLEND\n"
2950 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2951 "#endif\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 "uniform float4x4 ModelToLight : register(c20),\n"
2954 "#endif\n"
2955 "#ifdef MODE_LIGHTSOURCE\n"
2956 "uniform float3 LightPosition : register(c27),\n"
2957 "#endif\n"
2958 "#ifdef MODE_LIGHTDIRECTION\n"
2959 "uniform float3 LightDir : register(c26),\n"
2960 "#endif\n"
2961 "uniform float4 FogPlane : register(c25),\n"
2962 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2963 "uniform float3 LightPosition : register(c27),\n"
2964 "#endif\n"
2965 "#ifdef USESHADOWMAPORTHO\n"
2966 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2967 "#endif\n"
2968 "\n"
2969 "out float4 gl_FrontColor : COLOR,\n"
2970 "out float4 TexCoordBoth : TEXCOORD0,\n"
2971 "#ifdef USELIGHTMAP\n"
2972 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2973 "#endif\n"
2974 "#ifdef USEEYEVECTOR\n"
2975 "out float3 EyeVector : TEXCOORD2,\n"
2976 "#endif\n"
2977 "#ifdef USEREFLECTION\n"
2978 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2979 "#endif\n"
2980 "#ifdef USEFOG\n"
2981 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2982 "#endif\n"
2983 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2984 "out float3 LightVector : TEXCOORD1,\n"
2985 "#endif\n"
2986 "#ifdef MODE_LIGHTSOURCE\n"
2987 "out float3 CubeVector : TEXCOORD3,\n"
2988 "#endif\n"
2989 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2990 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2991 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2992 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2993 "#endif\n"
2994 "#ifdef USESHADOWMAPORTHO\n"
2995 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2996 "#endif\n"
2997 "out float4 gl_Position : POSITION\n"
2998 ")\n"
2999 "{\n"
3000 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
3001 "#ifdef HLSL\n"
3002 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
3003 "#else\n"
3004 "       gl_FrontColor = gl_Color; // Cg is forward\n"
3005 "#endif\n"
3006 "#endif\n"
3007 "       // copy the surface texcoord\n"
3008 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
3009 "#ifdef USEVERTEXTEXTUREBLEND\n"
3010 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
3011 "#endif\n"
3012 "#ifdef USELIGHTMAP\n"
3013 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
3014 "#endif\n"
3015 "\n"
3016 "#ifdef MODE_LIGHTSOURCE\n"
3017 "       // transform vertex position into light attenuation/cubemap space\n"
3018 "       // (-1 to +1 across the light box)\n"
3019 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
3020 "\n"
3021 "# ifdef USEDIFFUSE\n"
3022 "       // transform unnormalized light direction into tangent space\n"
3023 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
3024 "       //  normalize it per pixel)\n"
3025 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
3026 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
3027 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
3028 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
3029 "# endif\n"
3030 "#endif\n"
3031 "\n"
3032 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
3033 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
3034 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
3035 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
3036 "#endif\n"
3037 "\n"
3038 "       // transform unnormalized eye direction into tangent space\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
3041 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
3042 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
3043 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
3044 "#endif\n"
3045 "\n"
3046 "#ifdef USEFOG\n"
3047 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
3048 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3049 "#endif\n"
3050 "\n"
3051 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3052 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3053 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3054 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3055 "#endif\n"
3056 "\n"
3057 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3058 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3059 "\n"
3060 "#ifdef USESHADOWMAPORTHO\n"
3061 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3062 "#endif\n"
3063 "\n"
3064 "#ifdef USEREFLECTION\n"
3065 "       ModelViewProjectionPosition = gl_Position;\n"
3066 "#endif\n"
3067 "}\n"
3068 "#endif // VERTEX_SHADER\n"
3069 "\n"
3070 "\n"
3071 "\n"
3072 "\n"
3073 "#ifdef FRAGMENT_SHADER\n"
3074 "void main\n"
3075 "(\n"
3076 "#ifdef USEDEFERREDLIGHTMAP\n"
3077 "#ifdef HLSL\n"
3078 "float2 Pixel : VPOS,\n"
3079 "#else\n"
3080 "float2 Pixel : WPOS,\n"
3081 "#endif\n"
3082 "#endif\n"
3083 "float4 gl_FrontColor : COLOR,\n"
3084 "float4 TexCoordBoth : TEXCOORD0,\n"
3085 "#ifdef USELIGHTMAP\n"
3086 "float2 TexCoordLightmap : TEXCOORD1,\n"
3087 "#endif\n"
3088 "#ifdef USEEYEVECTOR\n"
3089 "float3 EyeVector : TEXCOORD2,\n"
3090 "#endif\n"
3091 "#ifdef USEREFLECTION\n"
3092 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3093 "#endif\n"
3094 "#ifdef USEFOG\n"
3095 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3096 "#endif\n"
3097 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3098 "float3 LightVector : TEXCOORD1,\n"
3099 "#endif\n"
3100 "#ifdef MODE_LIGHTSOURCE\n"
3101 "float3 CubeVector : TEXCOORD3,\n"
3102 "#endif\n"
3103 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3104 "float4 ModelViewPosition : TEXCOORD0,\n"
3105 "#endif\n"
3106 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3107 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3108 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3109 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3110 "#endif\n"
3111 "#ifdef USESHADOWMAPORTHO\n"
3112 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3113 "#endif\n"
3114 "\n"
3115 "uniform sampler Texture_Normal : register(s0),\n"
3116 "uniform sampler Texture_Color : register(s1),\n"
3117 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3118 "uniform sampler Texture_Gloss : register(s2),\n"
3119 "#endif\n"
3120 "#ifdef USEGLOW\n"
3121 "uniform sampler Texture_Glow : register(s3),\n"
3122 "#endif\n"
3123 "#ifdef USEVERTEXTEXTUREBLEND\n"
3124 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3125 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3126 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3127 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3128 "#endif\n"
3129 "#ifdef USEGLOW\n"
3130 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3131 "#endif\n"
3132 "#endif\n"
3133 "#ifdef USECOLORMAPPING\n"
3134 "uniform sampler Texture_Pants : register(s4),\n"
3135 "uniform sampler Texture_Shirt : register(s7),\n"
3136 "#endif\n"
3137 "#ifdef USEFOG\n"
3138 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3139 "uniform sampler Texture_FogMask : register(s8),\n"
3140 "#endif\n"
3141 "#ifdef USELIGHTMAP\n"
3142 "uniform sampler Texture_Lightmap : register(s9),\n"
3143 "#endif\n"
3144 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3145 "uniform sampler Texture_Deluxemap : register(s10),\n"
3146 "#endif\n"
3147 "#ifdef USEREFLECTION\n"
3148 "uniform sampler Texture_Reflection : register(s7),\n"
3149 "#endif\n"
3150 "\n"
3151 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3152 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3153 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3154 "#endif\n"
3155 "#ifdef USEDEFERREDLIGHTMAP\n"
3156 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3157 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3158 "#endif\n"
3159 "\n"
3160 "#ifdef USECOLORMAPPING\n"
3161 "uniform half3 Color_Pants : register(c7),\n"
3162 "uniform half3 Color_Shirt : register(c8),\n"
3163 "#endif\n"
3164 "#ifdef USEFOG\n"
3165 "uniform float3 FogColor : register(c16),\n"
3166 "uniform float FogRangeRecip : register(c20),\n"
3167 "uniform float FogPlaneViewDist : register(c19),\n"
3168 "uniform float FogHeightFade : register(c17),\n"
3169 "#endif\n"
3170 "\n"
3171 "#ifdef USEOFFSETMAPPING\n"
3172 "uniform float OffsetMapping_Scale : register(c24),\n"
3173 "#endif\n"
3174 "\n"
3175 "#ifdef USEDEFERREDLIGHTMAP\n"
3176 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3177 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3178 "uniform half3 DeferredMod_Specular : register(c13),\n"
3179 "#endif\n"
3180 "uniform half3 Color_Ambient : register(c3),\n"
3181 "uniform half3 Color_Diffuse : register(c4),\n"
3182 "uniform half3 Color_Specular : register(c5),\n"
3183 "uniform half SpecularPower : register(c36),\n"
3184 "#ifdef USEGLOW\n"
3185 "uniform half3 Color_Glow : register(c6),\n"
3186 "#endif\n"
3187 "uniform half Alpha : register(c0),\n"
3188 "#ifdef USEREFLECTION\n"
3189 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3190 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3191 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3192 "uniform half4 ReflectColor : register(c26),\n"
3193 "#endif\n"
3194 "#ifdef USEREFLECTCUBE\n"
3195 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3196 "uniform sampler Texture_ReflectMask : register(s5),\n"
3197 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3198 "#endif\n"
3199 "#ifdef MODE_LIGHTDIRECTION\n"
3200 "uniform half3 LightColor : register(c21),\n"
3201 "#endif\n"
3202 "#ifdef MODE_LIGHTSOURCE\n"
3203 "uniform half3 LightColor : register(c21),\n"
3204 "#endif\n"
3205 "\n"
3206 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3207 "uniform sampler Texture_Attenuation : register(s9),\n"
3208 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3209 "#endif\n"
3210 "\n"
3211 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3212 "\n"
3213 "#ifdef USESHADOWMAPRECT\n"
3214 "# ifdef USESHADOWSAMPLER\n"
3215 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3216 "# else\n"
3217 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3218 "# endif\n"
3219 "#endif\n"
3220 "\n"
3221 "#ifdef USESHADOWMAP2D\n"
3222 "# ifdef USESHADOWSAMPLER\n"
3223 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3224 "# else\n"
3225 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3226 "# endif\n"
3227 "#endif\n"
3228 "\n"
3229 "#ifdef USESHADOWMAPVSDCT\n"
3230 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3231 "#endif\n"
3232 "\n"
3233 "#ifdef USESHADOWMAPCUBE\n"
3234 "# ifdef USESHADOWSAMPLER\n"
3235 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3236 "# else\n"
3237 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3238 "# endif\n"
3239 "#endif\n"
3240 "\n"
3241 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3242 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3243 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3244 "#endif\n"
3245 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3246 "\n"
3247 "out float4 gl_FragColor : COLOR\n"
3248 ")\n"
3249 "{\n"
3250 "       float2 TexCoord = TexCoordBoth.xy;\n"
3251 "#ifdef USEVERTEXTEXTUREBLEND\n"
3252 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3253 "#endif\n"
3254 "#ifdef USEOFFSETMAPPING\n"
3255 "       // apply offsetmapping\n"
3256 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3257 "#define TexCoord TexCoordOffset\n"
3258 "#endif\n"
3259 "\n"
3260 "       // combine the diffuse textures (base, pants, shirt)\n"
3261 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3262 "#ifdef USEALPHAKILL\n"
3263 "       if (color.a < 0.5)\n"
3264 "               discard;\n"
3265 "#endif\n"
3266 "       color.a *= Alpha;\n"
3267 "#ifdef USECOLORMAPPING\n"
3268 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3269 "#endif\n"
3270 "#ifdef USEVERTEXTEXTUREBLEND\n"
3271 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3272 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3273 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3274 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3275 "       color.a = 1.0;\n"
3276 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3277 "#endif\n"
3278 "\n"
3279 "       // get the surface normal\n"
3280 "#ifdef USEVERTEXTEXTUREBLEND\n"
3281 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3282 "#else\n"
3283 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3284 "#endif\n"
3285 "\n"
3286 "       // get the material colors\n"
3287 "       half3 diffusetex = color.rgb;\n"
3288 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3289 "# ifdef USEVERTEXTEXTUREBLEND\n"
3290 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3291 "# else\n"
3292 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3293 "# endif\n"
3294 "#endif\n"
3295 "\n"
3296 "#ifdef USEREFLECTCUBE\n"
3297 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3298 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3299 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3300 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3301 "#endif\n"
3302 "\n"
3303 "\n"
3304 "\n"
3305 "\n"
3306 "#ifdef MODE_LIGHTSOURCE\n"
3307 "       // light source\n"
3308 "#ifdef USEDIFFUSE\n"
3309 "       half3 lightnormal = half3(normalize(LightVector));\n"
3310 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3311 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3312 "#ifdef USESPECULAR\n"
3313 "#ifdef USEEXACTSPECULARMATH\n"
3314 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3315 "#else\n"
3316 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3317 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3318 "#endif\n"
3319 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3320 "#endif\n"
3321 "#else\n"
3322 "       color.rgb = diffusetex * Color_Ambient;\n"
3323 "#endif\n"
3324 "       color.rgb *= LightColor;\n"
3325 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3326 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3327 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3328 "# if defined(USESHADOWMAP2D)\n"
3329 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3330 "# endif\n"
3331 "# if defined(USESHADOWMAPRECT)\n"
3332 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3333 "# endif\n"
3334 "# if defined(USESHADOWMAPCUBE)\n"
3335 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3336 "# endif\n"
3337 "\n"
3338 "#ifdef USESHADOWMAPVSDCT\n"
3339 ", Texture_CubeProjection\n"
3340 "#endif\n"
3341 "       ));\n"
3342 "\n"
3343 "#endif\n"
3344 "# ifdef USECUBEFILTER\n"
3345 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3346 "# endif\n"
3347 "\n"
3348 "#ifdef USESHADOWMAP2D\n"
3349 "#ifdef USESHADOWMAPVSDCT\n"
3350 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3351 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3352 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3353 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3354 "#else\n"
3355 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3356 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3357 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3358 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3359 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3360 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3361 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3362 "//     color.r = half(shadowmaptc.z);\n"
3363 "#endif\n"
3364 "//     color.r = 1;\n"
3365 "#endif\n"
3366 "//     color.rgb = half3(1,1,1);\n"
3367 "#endif // MODE_LIGHTSOURCE\n"
3368 "\n"
3369 "\n"
3370 "\n"
3371 "\n"
3372 "#ifdef MODE_LIGHTDIRECTION\n"
3373 "#define SHADING\n"
3374 "#ifdef USEDIFFUSE\n"
3375 "       half3 lightnormal = half3(normalize(LightVector));\n"
3376 "#endif\n"
3377 "#define lightcolor LightColor\n"
3378 "#endif // MODE_LIGHTDIRECTION\n"
3379 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3380 "#define SHADING\n"
3381 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3382 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3383 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3384 "       // convert modelspace light vector to tangentspace\n"
3385 "       half3 lightnormal;\n"
3386 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3387 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3388 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3389 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3390 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3391 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3392 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3393 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3394 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3395 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3396 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3397 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3398 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3399 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3400 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3401 "#define SHADING\n"
3402 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3403 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3404 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3405 "#endif\n"
3406 "\n"
3407 "\n"
3408 "\n"
3409 "\n"
3410 "#ifdef MODE_LIGHTMAP\n"
3411 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3412 "#endif // MODE_LIGHTMAP\n"
3413 "#ifdef MODE_VERTEXCOLOR\n"
3414 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3415 "#endif // MODE_VERTEXCOLOR\n"
3416 "#ifdef MODE_FLATCOLOR\n"
3417 "       color.rgb = diffusetex * Color_Ambient;\n"
3418 "#endif // MODE_FLATCOLOR\n"
3419 "\n"
3420 "\n"
3421 "\n"
3422 "\n"
3423 "#ifdef SHADING\n"
3424 "# ifdef USEDIFFUSE\n"
3425 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3426 "#  ifdef USESPECULAR\n"
3427 "#   ifdef USEEXACTSPECULARMATH\n"
3428 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3429 "#   else\n"
3430 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3431 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3432 "#   endif\n"
3433 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3434 "#  else\n"
3435 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3436 "#  endif\n"
3437 "# else\n"
3438 "       color.rgb = diffusetex * Color_Ambient;\n"
3439 "# endif\n"
3440 "#endif\n"
3441 "\n"
3442 "#ifdef USESHADOWMAPORTHO\n"
3443 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3444 "# if defined(USESHADOWMAP2D)\n"
3445 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3446 "# endif\n"
3447 "# if defined(USESHADOWMAPRECT)\n"
3448 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3449 "# endif\n"
3450 "       );\n"
3451 "#endif\n"
3452 "\n"
3453 "#ifdef USEDEFERREDLIGHTMAP\n"
3454 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3455 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3456 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3457 "#endif\n"
3458 "\n"
3459 "#ifdef USEGLOW\n"
3460 "#ifdef USEVERTEXTEXTUREBLEND\n"
3461 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3462 "#else\n"
3463 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3464 "#endif\n"
3465 "#endif\n"
3466 "\n"
3467 "#ifdef USEFOG\n"
3468 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3469 "#endif\n"
3470 "\n"
3471 "       // 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"
3472 "#ifdef USEREFLECTION\n"
3473 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3474 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3475 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3476 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3477 "       // FIXME temporary hack to detect the case that the reflection\n"
3478 "       // gets blackened at edges due to leaving the area that contains actual\n"
3479 "       // content.\n"
3480 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3481 "       // 'appening.\n"
3482 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3483 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3484 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3485 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3486 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3487 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3488 "#endif\n"
3489 "\n"
3490 "       gl_FragColor = float4(color);\n"
3491 "}\n"
3492 "#endif // FRAGMENT_SHADER\n"
3493 "\n"
3494 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3495 "#endif // !MODE_DEFERREDGEOMETRY\n"
3496 "#endif // !MODE_WATER\n"
3497 "#endif // !MODE_REFRACTION\n"
3498 "#endif // !MODE_BLOOMBLUR\n"
3499 "#endif // !MODE_GENERIC\n"
3500 "#endif // !MODE_POSTPROCESS\n"
3501 "#endif // !MODE_SHOWDEPTH\n"
3502 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3503 ;
3504
3505 char *glslshaderstring = NULL;
3506 char *cgshaderstring = NULL;
3507 char *hlslshaderstring = NULL;
3508
3509 //=======================================================================================================================================================
3510
3511 typedef struct shaderpermutationinfo_s
3512 {
3513         const char *pretext;
3514         const char *name;
3515 }
3516 shaderpermutationinfo_t;
3517
3518 typedef struct shadermodeinfo_s
3519 {
3520         const char *vertexfilename;
3521         const char *geometryfilename;
3522         const char *fragmentfilename;
3523         const char *pretext;
3524         const char *name;
3525 }
3526 shadermodeinfo_t;
3527
3528 typedef enum shaderpermutation_e
3529 {
3530         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3531         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3532         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3533         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3534         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3535         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3536         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3537         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3538         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3539         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3540         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3541         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3542         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3543         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3544         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3545         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3546         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3547         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3548         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3549         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3550         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3551         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3552         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3553         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3554         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3555         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3556         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3557         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3558         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3559         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3560         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3561 }
3562 shaderpermutation_t;
3563
3564 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3565 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3566 {
3567         {"#define USEDIFFUSE\n", " diffuse"},
3568         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3569         {"#define USEVIEWTINT\n", " viewtint"},
3570         {"#define USECOLORMAPPING\n", " colormapping"},
3571         {"#define USESATURATION\n", " saturation"},
3572         {"#define USEFOGINSIDE\n", " foginside"},
3573         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3574         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3575         {"#define USEGAMMARAMPS\n", " gammaramps"},
3576         {"#define USECUBEFILTER\n", " cubefilter"},
3577         {"#define USEGLOW\n", " glow"},
3578         {"#define USEBLOOM\n", " bloom"},
3579         {"#define USESPECULAR\n", " specular"},
3580         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3581         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3582         {"#define USEREFLECTION\n", " reflection"},
3583         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3584         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3585         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3586         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3587         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3588         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3589         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3590         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3591         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3592         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3593         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3594         {"#define USEALPHAKILL\n", " alphakill"},
3595         {"#define USEREFLECTCUBE\n", " reflectcube"},
3596 };
3597
3598 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3599 typedef enum shadermode_e
3600 {
3601         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3602         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3603         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3604         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3605         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3606         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3607         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3608         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3609         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3610         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3611         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3612         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3613         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3614         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3615         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3616         SHADERMODE_COUNT
3617 }
3618 shadermode_t;
3619
3620 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3621 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3622 {
3623         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3624         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3625         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3626         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3627         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3628         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3629         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3630         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3631         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3632         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3633         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3634         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3635         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3636         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3637         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3638 };
3639
3640 #ifdef SUPPORTCG
3641 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3642 {
3643         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3644         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3645         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3646         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3647         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3648         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3649         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3650         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3651         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3652         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3653         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3654         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3655         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3656         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3657         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3658 };
3659 #endif
3660
3661 #ifdef SUPPORTD3D
3662 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3663 {
3664         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3665         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3666         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3667         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3668         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3669         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3670         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3671         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3672         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3673         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3674         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3675         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3676         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3677         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3678         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3679 };
3680 #endif
3681
3682 struct r_glsl_permutation_s;
3683 typedef struct r_glsl_permutation_s
3684 {
3685         /// hash lookup data
3686         struct r_glsl_permutation_s *hashnext;
3687         unsigned int mode;
3688         unsigned int permutation;
3689
3690         /// indicates if we have tried compiling this permutation already
3691         qboolean compiled;
3692         /// 0 if compilation failed
3693         int program;
3694         /// locations of detected uniforms in program object, or -1 if not found
3695         int loc_Texture_First;
3696         int loc_Texture_Second;
3697         int loc_Texture_GammaRamps;
3698         int loc_Texture_Normal;
3699         int loc_Texture_Color;
3700         int loc_Texture_Gloss;
3701         int loc_Texture_Glow;
3702         int loc_Texture_SecondaryNormal;
3703         int loc_Texture_SecondaryColor;
3704         int loc_Texture_SecondaryGloss;
3705         int loc_Texture_SecondaryGlow;
3706         int loc_Texture_Pants;
3707         int loc_Texture_Shirt;
3708         int loc_Texture_FogHeightTexture;
3709         int loc_Texture_FogMask;
3710         int loc_Texture_Lightmap;
3711         int loc_Texture_Deluxemap;
3712         int loc_Texture_Attenuation;
3713         int loc_Texture_Cube;
3714         int loc_Texture_Refraction;
3715         int loc_Texture_Reflection;
3716         int loc_Texture_ShadowMapRect;
3717         int loc_Texture_ShadowMapCube;
3718         int loc_Texture_ShadowMap2D;
3719         int loc_Texture_CubeProjection;
3720         int loc_Texture_ScreenDepth;
3721         int loc_Texture_ScreenNormalMap;
3722         int loc_Texture_ScreenDiffuse;
3723         int loc_Texture_ScreenSpecular;
3724         int loc_Texture_ReflectMask;
3725         int loc_Texture_ReflectCube;
3726         int loc_Alpha;
3727         int loc_BloomBlur_Parameters;
3728         int loc_ClientTime;
3729         int loc_Color_Ambient;
3730         int loc_Color_Diffuse;
3731         int loc_Color_Specular;
3732         int loc_Color_Glow;
3733         int loc_Color_Pants;
3734         int loc_Color_Shirt;
3735         int loc_DeferredColor_Ambient;
3736         int loc_DeferredColor_Diffuse;
3737         int loc_DeferredColor_Specular;
3738         int loc_DeferredMod_Diffuse;
3739         int loc_DeferredMod_Specular;
3740         int loc_DistortScaleRefractReflect;
3741         int loc_EyePosition;
3742         int loc_FogColor;
3743         int loc_FogHeightFade;
3744         int loc_FogPlane;
3745         int loc_FogPlaneViewDist;
3746         int loc_FogRangeRecip;
3747         int loc_LightColor;
3748         int loc_LightDir;
3749         int loc_LightPosition;
3750         int loc_OffsetMapping_Scale;
3751         int loc_PixelSize;
3752         int loc_ReflectColor;
3753         int loc_ReflectFactor;
3754         int loc_ReflectOffset;
3755         int loc_RefractColor;
3756         int loc_Saturation;
3757         int loc_ScreenCenterRefractReflect;
3758         int loc_ScreenScaleRefractReflect;
3759         int loc_ScreenToDepth;
3760         int loc_ShadowMap_Parameters;
3761         int loc_ShadowMap_TextureScale;
3762         int loc_SpecularPower;
3763         int loc_UserVec1;
3764         int loc_UserVec2;
3765         int loc_UserVec3;
3766         int loc_UserVec4;
3767         int loc_ViewTintColor;
3768         int loc_ViewToLight;
3769         int loc_ModelToLight;
3770         int loc_TexMatrix;
3771         int loc_BackgroundTexMatrix;
3772         int loc_ModelViewProjectionMatrix;
3773         int loc_ModelViewMatrix;
3774         int loc_PixelToScreenTexCoord;
3775         int loc_ModelToReflectCube;
3776         int loc_ShadowMapMatrix;
3777         int loc_BloomColorSubtract;
3778 }
3779 r_glsl_permutation_t;
3780
3781 #define SHADERPERMUTATION_HASHSIZE 256
3782
3783 /// information about each possible shader permutation
3784 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3785 /// currently selected permutation
3786 r_glsl_permutation_t *r_glsl_permutation;
3787 /// storage for permutations linked in the hash table
3788 memexpandablearray_t r_glsl_permutationarray;
3789
3790 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3791 {
3792         //unsigned int hashdepth = 0;
3793         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3794         r_glsl_permutation_t *p;
3795         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3796         {
3797                 if (p->mode == mode && p->permutation == permutation)
3798                 {
3799                         //if (hashdepth > 10)
3800                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3801                         return p;
3802                 }
3803                 //hashdepth++;
3804         }
3805         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3806         p->mode = mode;
3807         p->permutation = permutation;
3808         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3809         r_glsl_permutationhash[mode][hashindex] = p;
3810         //if (hashdepth > 10)
3811         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3812         return p;
3813 }
3814
3815 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3816 {
3817         char *shaderstring;
3818         if (!filename || !filename[0])
3819                 return NULL;
3820         if (!strcmp(filename, "glsl/default.glsl"))
3821         {
3822                 if (!glslshaderstring)
3823                 {
3824                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3825                         if (glslshaderstring)
3826                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3827                         else
3828                                 glslshaderstring = (char *)builtinshaderstring;
3829                 }
3830                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3831                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3832                 return shaderstring;
3833         }
3834         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3835         if (shaderstring)
3836         {
3837                 if (printfromdisknotice)
3838                         Con_DPrintf("from disk %s... ", filename);
3839                 return shaderstring;
3840         }
3841         return shaderstring;
3842 }
3843
3844 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3845 {
3846         int i;
3847         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3848         int vertstrings_count = 0;
3849         int geomstrings_count = 0;
3850         int fragstrings_count = 0;
3851         char *vertexstring, *geometrystring, *fragmentstring;
3852         const char *vertstrings_list[32+3];
3853         const char *geomstrings_list[32+3];
3854         const char *fragstrings_list[32+3];
3855         char permutationname[256];
3856
3857         if (p->compiled)
3858                 return;
3859         p->compiled = true;
3860         p->program = 0;
3861
3862         permutationname[0] = 0;
3863         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3864         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3865         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3866
3867         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3868
3869         // the first pretext is which type of shader to compile as
3870         // (later these will all be bound together as a program object)
3871         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3872         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3873         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3874
3875         // the second pretext is the mode (for example a light source)
3876         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3877         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3878         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3879         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3880
3881         // now add all the permutation pretexts
3882         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3883         {
3884                 if (permutation & (1<<i))
3885                 {
3886                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3887                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3888                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3889                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3890                 }
3891                 else
3892                 {
3893                         // keep line numbers correct
3894                         vertstrings_list[vertstrings_count++] = "\n";
3895                         geomstrings_list[geomstrings_count++] = "\n";
3896                         fragstrings_list[fragstrings_count++] = "\n";
3897                 }
3898         }
3899
3900         // now append the shader text itself
3901         vertstrings_list[vertstrings_count++] = vertexstring;
3902         geomstrings_list[geomstrings_count++] = geometrystring;
3903         fragstrings_list[fragstrings_count++] = fragmentstring;
3904
3905         // if any sources were NULL, clear the respective list
3906         if (!vertexstring)
3907                 vertstrings_count = 0;
3908         if (!geometrystring)
3909                 geomstrings_count = 0;
3910         if (!fragmentstring)
3911                 fragstrings_count = 0;
3912
3913         // compile the shader program
3914         if (vertstrings_count + geomstrings_count + fragstrings_count)
3915                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3916         if (p->program)
3917         {
3918                 CHECKGLERROR
3919                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3920                 // look up all the uniform variable names we care about, so we don't
3921                 // have to look them up every time we set them
3922
3923                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3924                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3925                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3926                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3927                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3928                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3929                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3930                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3931                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3932                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3933                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3934                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3935                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3936                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3937                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3938                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3939                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3940                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3941                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3942                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3943                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3944                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3945                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3946                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3947                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3948                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3949                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3950                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3951                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3952                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3953                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3954                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3955                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3956                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3957                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3958                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3959                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3960                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3961                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3962                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3963                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3964                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3965                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3966                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3967                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3968                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3969                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3970                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3971                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3972                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3973                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3974                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3975                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3976                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3977                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3978                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3979                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3980                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3981                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3982                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3983                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3984                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3985                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3986                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3987                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3988                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3989                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3990                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3991                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3992                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3993                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3994                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3995                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3996                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3997                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3998                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3999                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
4000                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
4001                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
4002                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
4003                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
4004                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
4005                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
4006                 // initialize the samplers to refer to the texture units we use
4007                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
4008                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
4009                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
4010                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
4011                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
4012                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
4013                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
4014                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
4015                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
4016                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
4017                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
4018                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
4019                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
4020                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
4021                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
4022                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
4023                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
4024                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
4025                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
4026                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
4027                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
4028                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
4029                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
4030                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
4031                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
4032                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
4033                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
4034                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
4035                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
4036                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
4037                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
4038                 CHECKGLERROR
4039                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
4040         }
4041         else
4042                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
4043
4044         // free the strings
4045         if (vertexstring)
4046                 Mem_Free(vertexstring);
4047         if (geometrystring)
4048                 Mem_Free(geometrystring);
4049         if (fragmentstring)
4050                 Mem_Free(fragmentstring);
4051 }
4052
4053 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4054 {
4055         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4056         if (r_glsl_permutation != perm)
4057         {
4058                 r_glsl_permutation = perm;
4059                 if (!r_glsl_permutation->program)
4060                 {
4061                         if (!r_glsl_permutation->compiled)
4062                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4063                         if (!r_glsl_permutation->program)
4064                         {
4065                                 // remove features until we find a valid permutation
4066                                 int i;
4067                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4068                                 {
4069                                         // reduce i more quickly whenever it would not remove any bits
4070                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4071                                         if (!(permutation & j))
4072                                                 continue;
4073                                         permutation -= j;
4074                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4075                                         if (!r_glsl_permutation->compiled)
4076                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4077                                         if (r_glsl_permutation->program)
4078                                                 break;
4079                                 }
4080                                 if (i >= SHADERPERMUTATION_COUNT)
4081                                 {
4082                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4083                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4084                                         qglUseProgramObjectARB(0);CHECKGLERROR
4085                                         return; // no bit left to clear, entire mode is broken
4086                                 }
4087                         }
4088                 }
4089                 CHECKGLERROR
4090                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4091         }
4092         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4093         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4094         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4095 }
4096
4097 #ifdef SUPPORTCG
4098 #include <Cg/cgGL.h>
4099 struct r_cg_permutation_s;
4100 typedef struct r_cg_permutation_s
4101 {
4102         /// hash lookup data
4103         struct r_cg_permutation_s *hashnext;
4104         unsigned int mode;
4105         unsigned int permutation;
4106
4107         /// indicates if we have tried compiling this permutation already
4108         qboolean compiled;
4109         /// 0 if compilation failed
4110         CGprogram vprogram;
4111         CGprogram fprogram;
4112         /// locations of detected parameters in programs, or NULL if not found
4113         CGparameter vp_EyePosition;
4114         CGparameter vp_FogPlane;
4115         CGparameter vp_LightDir;
4116         CGparameter vp_LightPosition;
4117         CGparameter vp_ModelToLight;
4118         CGparameter vp_TexMatrix;
4119         CGparameter vp_BackgroundTexMatrix;
4120         CGparameter vp_ModelViewProjectionMatrix;
4121         CGparameter vp_ModelViewMatrix;
4122         CGparameter vp_ShadowMapMatrix;
4123
4124         CGparameter fp_Texture_First;
4125         CGparameter fp_Texture_Second;
4126         CGparameter fp_Texture_GammaRamps;
4127         CGparameter fp_Texture_Normal;
4128         CGparameter fp_Texture_Color;
4129         CGparameter fp_Texture_Gloss;
4130         CGparameter fp_Texture_Glow;
4131         CGparameter fp_Texture_SecondaryNormal;
4132         CGparameter fp_Texture_SecondaryColor;
4133         CGparameter fp_Texture_SecondaryGloss;
4134         CGparameter fp_Texture_SecondaryGlow;
4135         CGparameter fp_Texture_Pants;
4136         CGparameter fp_Texture_Shirt;
4137         CGparameter fp_Texture_FogHeightTexture;
4138         CGparameter fp_Texture_FogMask;
4139         CGparameter fp_Texture_Lightmap;
4140         CGparameter fp_Texture_Deluxemap;
4141         CGparameter fp_Texture_Attenuation;
4142         CGparameter fp_Texture_Cube;
4143         CGparameter fp_Texture_Refraction;
4144         CGparameter fp_Texture_Reflection;
4145         CGparameter fp_Texture_ShadowMapRect;
4146         CGparameter fp_Texture_ShadowMapCube;
4147         CGparameter fp_Texture_ShadowMap2D;
4148         CGparameter fp_Texture_CubeProjection;
4149         CGparameter fp_Texture_ScreenDepth;
4150         CGparameter fp_Texture_ScreenNormalMap;
4151         CGparameter fp_Texture_ScreenDiffuse;
4152         CGparameter fp_Texture_ScreenSpecular;
4153         CGparameter fp_Texture_ReflectMask;
4154         CGparameter fp_Texture_ReflectCube;
4155         CGparameter fp_Alpha;
4156         CGparameter fp_BloomBlur_Parameters;
4157         CGparameter fp_ClientTime;
4158         CGparameter fp_Color_Ambient;
4159         CGparameter fp_Color_Diffuse;
4160         CGparameter fp_Color_Specular;
4161         CGparameter fp_Color_Glow;
4162         CGparameter fp_Color_Pants;
4163         CGparameter fp_Color_Shirt;
4164         CGparameter fp_DeferredColor_Ambient;
4165         CGparameter fp_DeferredColor_Diffuse;
4166         CGparameter fp_DeferredColor_Specular;
4167         CGparameter fp_DeferredMod_Diffuse;
4168         CGparameter fp_DeferredMod_Specular;
4169         CGparameter fp_DistortScaleRefractReflect;
4170         CGparameter fp_EyePosition;
4171         CGparameter fp_FogColor;
4172         CGparameter fp_FogHeightFade;
4173         CGparameter fp_FogPlane;
4174         CGparameter fp_FogPlaneViewDist;
4175         CGparameter fp_FogRangeRecip;
4176         CGparameter fp_LightColor;
4177         CGparameter fp_LightDir;
4178         CGparameter fp_LightPosition;
4179         CGparameter fp_OffsetMapping_Scale;
4180         CGparameter fp_PixelSize;
4181         CGparameter fp_ReflectColor;
4182         CGparameter fp_ReflectFactor;
4183         CGparameter fp_ReflectOffset;
4184         CGparameter fp_RefractColor;
4185         CGparameter fp_Saturation;
4186         CGparameter fp_ScreenCenterRefractReflect;
4187         CGparameter fp_ScreenScaleRefractReflect;
4188         CGparameter fp_ScreenToDepth;
4189         CGparameter fp_ShadowMap_Parameters;
4190         CGparameter fp_ShadowMap_TextureScale;
4191         CGparameter fp_SpecularPower;
4192         CGparameter fp_UserVec1;
4193         CGparameter fp_UserVec2;
4194         CGparameter fp_UserVec3;
4195         CGparameter fp_UserVec4;
4196         CGparameter fp_ViewTintColor;
4197         CGparameter fp_ViewToLight;
4198         CGparameter fp_PixelToScreenTexCoord;
4199         CGparameter fp_ModelToReflectCube;
4200         CGparameter fp_BloomColorSubtract;
4201 }
4202 r_cg_permutation_t;
4203
4204 /// information about each possible shader permutation
4205 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4206 /// currently selected permutation
4207 r_cg_permutation_t *r_cg_permutation;
4208 /// storage for permutations linked in the hash table
4209 memexpandablearray_t r_cg_permutationarray;
4210
4211 #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));}}
4212
4213 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4214 {
4215         //unsigned int hashdepth = 0;
4216         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4217         r_cg_permutation_t *p;
4218         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4219         {
4220                 if (p->mode == mode && p->permutation == permutation)
4221                 {
4222                         //if (hashdepth > 10)
4223                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4224                         return p;
4225                 }
4226                 //hashdepth++;
4227         }
4228         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4229         p->mode = mode;
4230         p->permutation = permutation;
4231         p->hashnext = r_cg_permutationhash[mode][hashindex];
4232         r_cg_permutationhash[mode][hashindex] = p;
4233         //if (hashdepth > 10)
4234         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4235         return p;
4236 }
4237
4238 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4239 {
4240         char *shaderstring;
4241         if (!filename || !filename[0])
4242                 return NULL;
4243         if (!strcmp(filename, "cg/default.cg"))
4244         {
4245                 if (!cgshaderstring)
4246                 {
4247                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4248                         if (cgshaderstring)
4249                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4250                         else
4251                                 cgshaderstring = (char *)builtincgshaderstring;
4252                 }
4253                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4254                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4255                 return shaderstring;
4256         }
4257         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4258         if (shaderstring)
4259         {
4260                 if (printfromdisknotice)
4261                         Con_DPrintf("from disk %s... ", filename);
4262                 return shaderstring;
4263         }
4264         return shaderstring;
4265 }
4266
4267 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4268 {
4269         // TODO: load or create .fp and .vp shader files
4270 }
4271
4272 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4273 {
4274         int i;
4275         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4276         int vertstrings_count = 0, vertstring_length = 0;
4277         int geomstrings_count = 0, geomstring_length = 0;
4278         int fragstrings_count = 0, fragstring_length = 0;
4279         char *t;
4280         char *vertexstring, *geometrystring, *fragmentstring;
4281         char *vertstring, *geomstring, *fragstring;
4282         const char *vertstrings_list[32+3];
4283         const char *geomstrings_list[32+3];
4284         const char *fragstrings_list[32+3];
4285         char permutationname[256];
4286         char cachename[256];
4287         CGprofile vertexProfile;
4288         CGprofile fragmentProfile;
4289
4290         if (p->compiled)
4291                 return;
4292         p->compiled = true;
4293         p->vprogram = NULL;
4294         p->fprogram = NULL;
4295
4296         permutationname[0] = 0;
4297         cachename[0] = 0;
4298         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4299         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4300         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4301
4302         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4303         strlcat(cachename, "cg/", sizeof(cachename));
4304
4305         // the first pretext is which type of shader to compile as
4306         // (later these will all be bound together as a program object)
4307         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4308         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4309         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4310
4311         // the second pretext is the mode (for example a light source)
4312         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4313         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4314         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4315         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4316         strlcat(cachename, modeinfo->name, sizeof(cachename));
4317
4318         // now add all the permutation pretexts
4319         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4320         {
4321                 if (permutation & (1<<i))
4322                 {
4323                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4324                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4325                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4326                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4327                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4328                 }
4329                 else
4330                 {
4331                         // keep line numbers correct
4332                         vertstrings_list[vertstrings_count++] = "\n";
4333                         geomstrings_list[geomstrings_count++] = "\n";
4334                         fragstrings_list[fragstrings_count++] = "\n";
4335                 }
4336         }
4337
4338         // replace spaces in the cachename with _ characters
4339         for (i = 0;cachename[i];i++)
4340                 if (cachename[i] == ' ')
4341                         cachename[i] = '_';
4342
4343         // now append the shader text itself
4344         vertstrings_list[vertstrings_count++] = vertexstring;
4345         geomstrings_list[geomstrings_count++] = geometrystring;
4346         fragstrings_list[fragstrings_count++] = fragmentstring;
4347
4348         // if any sources were NULL, clear the respective list
4349         if (!vertexstring)
4350                 vertstrings_count = 0;
4351         if (!geometrystring)
4352                 geomstrings_count = 0;
4353         if (!fragmentstring)
4354                 fragstrings_count = 0;
4355
4356         vertstring_length = 0;
4357         for (i = 0;i < vertstrings_count;i++)
4358                 vertstring_length += strlen(vertstrings_list[i]);
4359         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4360         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4361                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4362
4363         geomstring_length = 0;
4364         for (i = 0;i < geomstrings_count;i++)
4365                 geomstring_length += strlen(geomstrings_list[i]);
4366         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4367         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4368                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4369
4370         fragstring_length = 0;
4371         for (i = 0;i < fragstrings_count;i++)
4372                 fragstring_length += strlen(fragstrings_list[i]);
4373         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4374         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4375                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4376
4377         CHECKGLERROR
4378         CHECKCGERROR
4379         //vertexProfile = CG_PROFILE_ARBVP1;
4380         //fragmentProfile = CG_PROFILE_ARBFP1;
4381         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4382         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4383         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4384         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4385         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4386         CHECKGLERROR
4387
4388         // try to load the cached shader, or generate one
4389         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4390
4391         // if caching failed, do a dynamic compile for now
4392         CHECKCGERROR
4393         if (vertstring[0] && !p->vprogram)
4394                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4395         CHECKCGERROR
4396         if (fragstring[0] && !p->fprogram)
4397                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4398         CHECKCGERROR
4399
4400         // look up all the uniform variable names we care about, so we don't
4401         // have to look them up every time we set them
4402         if (p->vprogram)
4403         {
4404                 CHECKCGERROR
4405                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4406                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4407                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4408                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4409                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4410                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4411                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4412                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4413                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4414                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4415                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4416                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4417                 CHECKCGERROR
4418         }
4419         if (p->fprogram)
4420         {
4421                 CHECKCGERROR
4422                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4423                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4424                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4425                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4426                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4427                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4428                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4429                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4430                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4431                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4432                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4433                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4434                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4435                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4436                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4437                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4438                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4439                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4440                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4441                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4442                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4443                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4444                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4445                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4446                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4447                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4448                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4449                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4450                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4451                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4452                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4453                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4454                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4455                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4456                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4457                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4458                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4459                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4460                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4461                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4462                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4463                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4464                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4465                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4466                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4467                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4468                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4469                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4470                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4471                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4472                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4473                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4474                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4475                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4476                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4477                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4478                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4479                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4480                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4481                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4482                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4483                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4484                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4485                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4486                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4487                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4488                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4489                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4490                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4491                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4492                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4493                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4494                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4495                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4496                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4497                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4498                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4499                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4500                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4501                 CHECKCGERROR
4502         }
4503
4504         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4505                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4506         else
4507                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4508
4509         // free the strings
4510         if (vertstring)
4511                 Mem_Free(vertstring);
4512         if (geomstring)
4513                 Mem_Free(geomstring);
4514         if (fragstring)
4515                 Mem_Free(fragstring);
4516         if (vertexstring)
4517                 Mem_Free(vertexstring);
4518         if (geometrystring)
4519                 Mem_Free(geometrystring);
4520         if (fragmentstring)
4521                 Mem_Free(fragmentstring);
4522 }
4523
4524 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4525 {
4526         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4527         CHECKGLERROR
4528         CHECKCGERROR
4529         if (r_cg_permutation != perm)
4530         {
4531                 r_cg_permutation = perm;
4532                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4533                 {
4534                         if (!r_cg_permutation->compiled)
4535                                 R_CG_CompilePermutation(perm, mode, permutation);
4536                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4537                         {
4538                                 // remove features until we find a valid permutation
4539                                 int i;
4540                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4541                                 {
4542                                         // reduce i more quickly whenever it would not remove any bits
4543                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4544                                         if (!(permutation & j))
4545                                                 continue;
4546                                         permutation -= j;
4547                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4548                                         if (!r_cg_permutation->compiled)
4549                                                 R_CG_CompilePermutation(perm, mode, permutation);
4550                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4551                                                 break;
4552                                 }
4553                                 if (i >= SHADERPERMUTATION_COUNT)
4554                                 {
4555                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4556                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4557                                         return; // no bit left to clear, entire mode is broken
4558                                 }
4559                         }
4560                 }
4561                 CHECKGLERROR
4562                 CHECKCGERROR
4563                 if (r_cg_permutation->vprogram)
4564                 {
4565                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4566                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4567                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4568                 }
4569                 else
4570                 {
4571                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4572                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4573                 }
4574                 if (r_cg_permutation->fprogram)
4575                 {
4576                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4577                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4578                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4579                 }
4580                 else
4581                 {
4582                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4583                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4584                 }
4585         }
4586         CHECKCGERROR
4587         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4588         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4589         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4590 }
4591
4592 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4593 {
4594         cgGLSetTextureParameter(param, R_GetTexture(tex));
4595         cgGLEnableTextureParameter(param);
4596 }
4597 #endif
4598
4599 #ifdef SUPPORTD3D
4600
4601 #ifdef SUPPORTD3D
4602 #include <d3d9.h>
4603 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4604 extern D3DCAPS9 vid_d3d9caps;
4605 #endif
4606
4607 struct r_hlsl_permutation_s;
4608 typedef struct r_hlsl_permutation_s
4609 {
4610         /// hash lookup data
4611         struct r_hlsl_permutation_s *hashnext;
4612         unsigned int mode;
4613         unsigned int permutation;
4614
4615         /// indicates if we have tried compiling this permutation already
4616         qboolean compiled;
4617         /// NULL if compilation failed
4618         IDirect3DVertexShader9 *vertexshader;
4619         IDirect3DPixelShader9 *pixelshader;
4620 }
4621 r_hlsl_permutation_t;
4622
4623 typedef enum D3DVSREGISTER_e
4624 {
4625         D3DVSREGISTER_TexMatrix = 0, // float4x4
4626         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4627         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4628         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4629         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4630         D3DVSREGISTER_ModelToLight = 20, // float4x4
4631         D3DVSREGISTER_EyePosition = 24,
4632         D3DVSREGISTER_FogPlane = 25,
4633         D3DVSREGISTER_LightDir = 26,
4634         D3DVSREGISTER_LightPosition = 27,
4635 }
4636 D3DVSREGISTER_t;
4637
4638 typedef enum D3DPSREGISTER_e
4639 {
4640         D3DPSREGISTER_Alpha = 0,
4641         D3DPSREGISTER_BloomBlur_Parameters = 1,
4642         D3DPSREGISTER_ClientTime = 2,
4643         D3DPSREGISTER_Color_Ambient = 3,
4644         D3DPSREGISTER_Color_Diffuse = 4,
4645         D3DPSREGISTER_Color_Specular = 5,
4646         D3DPSREGISTER_Color_Glow = 6,
4647         D3DPSREGISTER_Color_Pants = 7,
4648         D3DPSREGISTER_Color_Shirt = 8,
4649         D3DPSREGISTER_DeferredColor_Ambient = 9,
4650         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4651         D3DPSREGISTER_DeferredColor_Specular = 11,
4652         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4653         D3DPSREGISTER_DeferredMod_Specular = 13,
4654         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4655         D3DPSREGISTER_EyePosition = 15, // unused
4656         D3DPSREGISTER_FogColor = 16,
4657         D3DPSREGISTER_FogHeightFade = 17,
4658         D3DPSREGISTER_FogPlane = 18,
4659         D3DPSREGISTER_FogPlaneViewDist = 19,
4660         D3DPSREGISTER_FogRangeRecip = 20,
4661         D3DPSREGISTER_LightColor = 21,
4662         D3DPSREGISTER_LightDir = 22, // unused
4663         D3DPSREGISTER_LightPosition = 23,
4664         D3DPSREGISTER_OffsetMapping_Scale = 24,
4665         D3DPSREGISTER_PixelSize = 25,
4666         D3DPSREGISTER_ReflectColor = 26,
4667         D3DPSREGISTER_ReflectFactor = 27,
4668         D3DPSREGISTER_ReflectOffset = 28,
4669         D3DPSREGISTER_RefractColor = 29,
4670         D3DPSREGISTER_Saturation = 30,
4671         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4672         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4673         D3DPSREGISTER_ScreenToDepth = 33,
4674         D3DPSREGISTER_ShadowMap_Parameters = 34,
4675         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4676         D3DPSREGISTER_SpecularPower = 36,
4677         D3DPSREGISTER_UserVec1 = 37,
4678         D3DPSREGISTER_UserVec2 = 38,
4679         D3DPSREGISTER_UserVec3 = 39,
4680         D3DPSREGISTER_UserVec4 = 40,
4681         D3DPSREGISTER_ViewTintColor = 41,
4682         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4683         D3DPSREGISTER_BloomColorSubtract = 43,
4684         D3DPSREGISTER_ViewToLight = 44, // float4x4
4685         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4686         // next at 52
4687 }
4688 D3DPSREGISTER_t;
4689
4690 /// information about each possible shader permutation
4691 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4692 /// currently selected permutation
4693 r_hlsl_permutation_t *r_hlsl_permutation;
4694 /// storage for permutations linked in the hash table
4695 memexpandablearray_t r_hlsl_permutationarray;
4696
4697 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4698 {
4699         //unsigned int hashdepth = 0;
4700         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4701         r_hlsl_permutation_t *p;
4702         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4703         {
4704                 if (p->mode == mode && p->permutation == permutation)
4705                 {
4706                         //if (hashdepth > 10)
4707                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4708                         return p;
4709                 }
4710                 //hashdepth++;
4711         }
4712         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4713         p->mode = mode;
4714         p->permutation = permutation;
4715         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4716         r_hlsl_permutationhash[mode][hashindex] = p;
4717         //if (hashdepth > 10)
4718         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4719         return p;
4720 }
4721
4722 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4723 {
4724         char *shaderstring;
4725         if (!filename || !filename[0])
4726                 return NULL;
4727         if (!strcmp(filename, "hlsl/default.hlsl"))
4728         {
4729                 if (!hlslshaderstring)
4730                 {
4731                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4732                         if (hlslshaderstring)
4733                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4734                         else
4735                                 hlslshaderstring = (char *)builtincgshaderstring;
4736                 }
4737                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4738                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4739                 return shaderstring;
4740         }
4741         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4742         if (shaderstring)
4743         {
4744                 if (printfromdisknotice)
4745                         Con_DPrintf("from disk %s... ", filename);
4746                 return shaderstring;
4747         }
4748         return shaderstring;
4749 }
4750
4751 #include <d3dx9.h>
4752 #include <d3dx9mesh.h>
4753 #pragma comment(lib, "d3dx9.lib")
4754
4755 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4756 {
4757         DWORD *vsbin = NULL;
4758         DWORD *psbin = NULL;
4759         fs_offset_t vsbinsize;
4760         fs_offset_t psbinsize;
4761 //      IDirect3DVertexShader9 *vs = NULL;
4762 //      IDirect3DPixelShader9 *ps = NULL;
4763         ID3DXBuffer *vslog = NULL;
4764         ID3DXBuffer *vsbuffer = NULL;
4765         ID3DXConstantTable *vsconstanttable = NULL;
4766         ID3DXBuffer *pslog = NULL;
4767         ID3DXBuffer *psbuffer = NULL;
4768         ID3DXConstantTable *psconstanttable = NULL;
4769         int vsresult = 0;
4770         int psresult = 0;
4771         char temp[MAX_INPUTLINE];
4772         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4773         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4774         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4775         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4776         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4777         if ((!vsbin && vertstring) || (!psbin && fragstring))
4778         {
4779                 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4780                 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4781                 if (vertstring && vertstring[0])
4782                 {
4783                         vsresult = D3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
4784                         if (vsbuffer)
4785                         {
4786                                 vsbinsize = vsbuffer->GetBufferSize();
4787                                 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4788                                 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4789                                 vsbuffer->Release();
4790                         }
4791                         if (vslog)
4792                         {
4793                                 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4794                                 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4795                                 vslog->Release();
4796                         }
4797                 }
4798                 if (fragstring && fragstring[0])
4799                 {
4800                         psresult = D3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
4801                         if (psbuffer)
4802                         {
4803                                 psbinsize = psbuffer->GetBufferSize();
4804                                 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4805                                 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4806                                 psbuffer->Release();
4807                         }
4808                         if (pslog)
4809                         {
4810                                 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4811                                 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4812                                 pslog->Release();
4813                         }
4814                 }
4815         }
4816         if (vsbin)
4817         {
4818                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4819                 if (FAILED(vsresult))
4820                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4821         }
4822         if (psbin)
4823         {
4824                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4825                 if (FAILED(psresult))
4826                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4827         }
4828         // free the shader data
4829         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4830         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4831 }
4832
4833 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4834 {
4835         int i;
4836         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4837         int vertstrings_count = 0, vertstring_length = 0;
4838         int geomstrings_count = 0, geomstring_length = 0;
4839         int fragstrings_count = 0, fragstring_length = 0;
4840         char *t;
4841         char *vertexstring, *geometrystring, *fragmentstring;
4842         char *vertstring, *geomstring, *fragstring;
4843         const char *vertstrings_list[32+3];
4844         const char *geomstrings_list[32+3];
4845         const char *fragstrings_list[32+3];
4846         char permutationname[256];
4847         char cachename[256];
4848
4849         if (p->compiled)
4850                 return;
4851         p->compiled = true;
4852         p->vertexshader = NULL;
4853         p->pixelshader = NULL;
4854
4855         permutationname[0] = 0;
4856         cachename[0] = 0;
4857         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4858         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4859         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4860
4861         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4862         strlcat(cachename, "hlsl/", sizeof(cachename));
4863
4864         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4865         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4866         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4867         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4868
4869         // the first pretext is which type of shader to compile as
4870         // (later these will all be bound together as a program object)
4871         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4872         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4873         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4874
4875         // the second pretext is the mode (for example a light source)
4876         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4877         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4878         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4879         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4880         strlcat(cachename, modeinfo->name, sizeof(cachename));
4881
4882         // now add all the permutation pretexts
4883         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4884         {
4885                 if (permutation & (1<<i))
4886                 {
4887                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4888                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4889                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4890                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4891                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4892                 }
4893                 else
4894                 {
4895                         // keep line numbers correct
4896                         vertstrings_list[vertstrings_count++] = "\n";
4897                         geomstrings_list[geomstrings_count++] = "\n";
4898                         fragstrings_list[fragstrings_count++] = "\n";
4899                 }
4900         }
4901
4902         // replace spaces in the cachename with _ characters
4903         for (i = 0;cachename[i];i++)
4904                 if (cachename[i] == ' ')
4905                         cachename[i] = '_';
4906
4907         // now append the shader text itself
4908         vertstrings_list[vertstrings_count++] = vertexstring;
4909         geomstrings_list[geomstrings_count++] = geometrystring;
4910         fragstrings_list[fragstrings_count++] = fragmentstring;
4911
4912         // if any sources were NULL, clear the respective list
4913         if (!vertexstring)
4914                 vertstrings_count = 0;
4915         if (!geometrystring)
4916                 geomstrings_count = 0;
4917         if (!fragmentstring)
4918                 fragstrings_count = 0;
4919
4920         vertstring_length = 0;
4921         for (i = 0;i < vertstrings_count;i++)
4922                 vertstring_length += strlen(vertstrings_list[i]);
4923         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4924         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4925                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4926
4927         geomstring_length = 0;
4928         for (i = 0;i < geomstrings_count;i++)
4929                 geomstring_length += strlen(geomstrings_list[i]);
4930         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4931         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4932                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4933
4934         fragstring_length = 0;
4935         for (i = 0;i < fragstrings_count;i++)
4936                 fragstring_length += strlen(fragstrings_list[i]);
4937         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4938         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4939                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4940
4941         // try to load the cached shader, or generate one
4942         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4943
4944         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4945                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4946         else
4947                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4948
4949         // free the strings
4950         if (vertstring)
4951                 Mem_Free(vertstring);
4952         if (geomstring)
4953                 Mem_Free(geomstring);
4954         if (fragstring)
4955                 Mem_Free(fragstring);
4956         if (vertexstring)
4957                 Mem_Free(vertexstring);
4958         if (geometrystring)
4959                 Mem_Free(geometrystring);
4960         if (fragmentstring)
4961                 Mem_Free(fragmentstring);
4962 }
4963
4964 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4965 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4966 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);}
4967 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);}
4968 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);}
4969 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);}
4970
4971 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4972 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4973 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);}
4974 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);}
4975 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);}
4976 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);}
4977
4978 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4979 {
4980         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4981         if (r_hlsl_permutation != perm)
4982         {
4983                 r_hlsl_permutation = perm;
4984                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4985                 {
4986                         if (!r_hlsl_permutation->compiled)
4987                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4988                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4989                         {
4990                                 // remove features until we find a valid permutation
4991                                 int i;
4992                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4993                                 {
4994                                         // reduce i more quickly whenever it would not remove any bits
4995                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4996                                         if (!(permutation & j))
4997                                                 continue;
4998                                         permutation -= j;
4999                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5000                                         if (!r_hlsl_permutation->compiled)
5001                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
5002                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
5003                                                 break;
5004                                 }
5005                                 if (i >= SHADERPERMUTATION_COUNT)
5006                                 {
5007                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5008                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5009                                         return; // no bit left to clear, entire mode is broken
5010                                 }
5011                         }
5012                 }
5013                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5014                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5015         }
5016         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5017         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5018         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5019 }
5020 #endif
5021
5022 void R_GLSL_Restart_f(void)
5023 {
5024         unsigned int i, limit;
5025         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5026                 Mem_Free(glslshaderstring);
5027         glslshaderstring = NULL;
5028         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5029                 Mem_Free(cgshaderstring);
5030         cgshaderstring = NULL;
5031         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5032                 Mem_Free(hlslshaderstring);
5033         hlslshaderstring = NULL;
5034         switch(vid.renderpath)
5035         {
5036         case RENDERPATH_D3D9:
5037 #ifdef SUPPORTD3D
5038                 {
5039                         r_hlsl_permutation_t *p;
5040                         r_hlsl_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_hlsl_permutationarray);
5046                         for (i = 0;i < limit;i++)
5047                         {
5048                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5049                                 {
5050                                         if (p->vertexshader)
5051                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5052                                         if (p->pixelshader)
5053                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5054                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5055                                 }
5056                         }
5057                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5058                 }
5059 #endif
5060                 break;
5061         case RENDERPATH_D3D10:
5062                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5063                 break;
5064         case RENDERPATH_D3D11:
5065                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5066                 break;
5067         case RENDERPATH_GL20:
5068                 {
5069                         r_glsl_permutation_t *p;
5070                         r_glsl_permutation = NULL;
5071                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5072                         for (i = 0;i < limit;i++)
5073                         {
5074                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5075                                 {
5076                                         GL_Backend_FreeProgram(p->program);
5077                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5078                                 }
5079                         }
5080                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5081                 }
5082                 break;
5083         case RENDERPATH_CGGL:
5084 #ifdef SUPPORTCG
5085                 {
5086                         r_cg_permutation_t *p;
5087                         r_cg_permutation = NULL;
5088                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5089                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5090                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5091                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5092                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5093                         for (i = 0;i < limit;i++)
5094                         {
5095                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5096                                 {
5097                                         if (p->vprogram)
5098                                                 cgDestroyProgram(p->vprogram);
5099                                         if (p->fprogram)
5100                                                 cgDestroyProgram(p->fprogram);
5101                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5102                                 }
5103                         }
5104                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5105                 }
5106 #endif
5107                 break;
5108         case RENDERPATH_GL13:
5109         case RENDERPATH_GL11:
5110                 break;
5111         }
5112 }
5113
5114 void R_GLSL_DumpShader_f(void)
5115 {
5116         int i;
5117         qfile_t *file;
5118
5119         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5120         if (file)
5121         {
5122                 FS_Print(file, "/* The engine may define the following macros:\n");
5123                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5124                 for (i = 0;i < SHADERMODE_COUNT;i++)
5125                         FS_Print(file, glslshadermodeinfo[i].pretext);
5126                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5127                         FS_Print(file, shaderpermutationinfo[i].pretext);
5128                 FS_Print(file, "*/\n");
5129                 FS_Print(file, builtinshaderstring);
5130                 FS_Close(file);
5131                 Con_Printf("glsl/default.glsl written\n");
5132         }
5133         else
5134                 Con_Printf("failed to write to glsl/default.glsl\n");
5135
5136 #ifdef SUPPORTCG
5137         file = FS_OpenRealFile("cg/default.cg", "w", false);
5138         if (file)
5139         {
5140                 FS_Print(file, "/* The engine may define the following macros:\n");
5141                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5142                 for (i = 0;i < SHADERMODE_COUNT;i++)
5143                         FS_Print(file, cgshadermodeinfo[i].pretext);
5144                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5145                         FS_Print(file, shaderpermutationinfo[i].pretext);
5146                 FS_Print(file, "*/\n");
5147                 FS_Print(file, builtincgshaderstring);
5148                 FS_Close(file);
5149                 Con_Printf("cg/default.cg written\n");
5150         }
5151         else
5152                 Con_Printf("failed to write to cg/default.cg\n");
5153 #endif
5154
5155 #ifdef SUPPORTD3D
5156         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5157         if (file)
5158         {
5159                 FS_Print(file, "/* The engine may define the following macros:\n");
5160                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5161                 for (i = 0;i < SHADERMODE_COUNT;i++)
5162                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5163                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5164                         FS_Print(file, shaderpermutationinfo[i].pretext);
5165                 FS_Print(file, "*/\n");
5166                 FS_Print(file, builtincgshaderstring);
5167                 FS_Close(file);
5168                 Con_Printf("hlsl/default.hlsl written\n");
5169         }
5170         else
5171                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5172 #endif
5173 }
5174
5175 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5176 {
5177         if (!second)
5178                 texturemode = GL_MODULATE;
5179         switch (vid.renderpath)
5180         {
5181         case RENDERPATH_D3D9:
5182 #ifdef SUPPORTD3D
5183                 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))));
5184                 R_Mesh_TexBind(GL20TU_FIRST , first );
5185                 R_Mesh_TexBind(GL20TU_SECOND, second);
5186 #endif
5187                 break;
5188         case RENDERPATH_D3D10:
5189                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5190                 break;
5191         case RENDERPATH_D3D11:
5192                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5193                 break;
5194         case RENDERPATH_GL20:
5195                 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))));
5196                 R_Mesh_TexBind(GL20TU_FIRST , first );
5197                 R_Mesh_TexBind(GL20TU_SECOND, second);
5198                 break;
5199         case RENDERPATH_CGGL:
5200 #ifdef SUPPORTCG
5201                 CHECKCGERROR
5202                 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))));
5203                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5204                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5205 #endif
5206                 break;
5207         case RENDERPATH_GL13:
5208                 R_Mesh_TexBind(0, first );
5209                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5210                 R_Mesh_TexBind(1, second);
5211                 if (second)
5212                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5213                 break;
5214         case RENDERPATH_GL11:
5215                 R_Mesh_TexBind(0, first );
5216                 break;
5217         }
5218 }
5219
5220 void R_SetupShader_DepthOrShadow(void)
5221 {
5222         switch (vid.renderpath)
5223         {
5224         case RENDERPATH_D3D9:
5225 #ifdef SUPPORTD3D
5226                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5227 #endif
5228                 break;
5229         case RENDERPATH_D3D10:
5230                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5231                 break;
5232         case RENDERPATH_D3D11:
5233                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5234                 break;
5235         case RENDERPATH_GL20:
5236                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5237                 break;
5238         case RENDERPATH_CGGL:
5239 #ifdef SUPPORTCG
5240                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5241 #endif
5242                 break;
5243         case RENDERPATH_GL13:
5244                 R_Mesh_TexBind(0, 0);
5245                 R_Mesh_TexBind(1, 0);
5246                 break;
5247         case RENDERPATH_GL11:
5248                 R_Mesh_TexBind(0, 0);
5249                 break;
5250         }
5251 }
5252
5253 void R_SetupShader_ShowDepth(void)
5254 {
5255         switch (vid.renderpath)
5256         {
5257         case RENDERPATH_D3D9:
5258 #ifdef SUPPORTHLSL
5259                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5260 #endif
5261                 break;
5262         case RENDERPATH_D3D10:
5263                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5264                 break;
5265         case RENDERPATH_D3D11:
5266                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5267                 break;
5268         case RENDERPATH_GL20:
5269                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5270                 break;
5271         case RENDERPATH_CGGL:
5272 #ifdef SUPPORTCG
5273                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5274 #endif
5275                 break;
5276         case RENDERPATH_GL13:
5277                 break;
5278         case RENDERPATH_GL11:
5279                 break;
5280         }
5281 }
5282
5283 extern qboolean r_shadow_usingdeferredprepass;
5284 extern cvar_t r_shadow_deferred_8bitrange;
5285 extern rtexture_t *r_shadow_attenuationgradienttexture;
5286 extern rtexture_t *r_shadow_attenuation2dtexture;
5287 extern rtexture_t *r_shadow_attenuation3dtexture;
5288 extern qboolean r_shadow_usingshadowmaprect;
5289 extern qboolean r_shadow_usingshadowmapcube;
5290 extern qboolean r_shadow_usingshadowmap2d;
5291 extern qboolean r_shadow_usingshadowmaportho;
5292 extern float r_shadow_shadowmap_texturescale[2];
5293 extern float r_shadow_shadowmap_parameters[4];
5294 extern qboolean r_shadow_shadowmapvsdct;
5295 extern qboolean r_shadow_shadowmapsampler;
5296 extern int r_shadow_shadowmappcf;
5297 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5298 extern rtexture_t *r_shadow_shadowmap2dtexture;
5299 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5300 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5301 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5302 extern matrix4x4_t r_shadow_shadowmapmatrix;
5303 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5304 extern int r_shadow_prepass_width;
5305 extern int r_shadow_prepass_height;
5306 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5307 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5308 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5309 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5310 extern cvar_t gl_mesh_separatearrays;
5311 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)
5312 {
5313         // select a permutation of the lighting shader appropriate to this
5314         // combination of texture, entity, light source, and fogging, only use the
5315         // minimum features necessary to avoid wasting rendering time in the
5316         // fragment shader on features that are not being used
5317         unsigned int permutation = 0;
5318         unsigned int mode = 0;
5319         float m16f[16];
5320         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5321         if (rsurfacepass == RSURFPASS_BACKGROUND)
5322         {
5323                 // distorted background
5324                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5325                         mode = SHADERMODE_WATER;
5326                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5327                         mode = SHADERMODE_REFRACTION;
5328                 else
5329                 {
5330                         mode = SHADERMODE_GENERIC;
5331                         permutation |= SHADERPERMUTATION_DIFFUSE;
5332                 }
5333                 GL_AlphaTest(false);
5334                 GL_BlendFunc(GL_ONE, GL_ZERO);
5335         }
5336         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5337         {
5338                 if (r_glsl_offsetmapping.integer)
5339                 {
5340                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5341                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5342                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5343                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5344                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5345                         {
5346                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5347                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5348                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5349                         }
5350                 }
5351                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5352                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5354                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5355                 // normalmap (deferred prepass), may use alpha test on diffuse
5356                 mode = SHADERMODE_DEFERREDGEOMETRY;
5357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5358                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5359                 GL_AlphaTest(false);
5360                 GL_BlendFunc(GL_ONE, GL_ZERO);
5361         }
5362         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5363         {
5364                 if (r_glsl_offsetmapping.integer)
5365                 {
5366                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5367                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5368                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5369                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5370                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5371                         {
5372                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5373                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5374                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5375                         }
5376                 }
5377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5378                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5379                 // light source
5380                 mode = SHADERMODE_LIGHTSOURCE;
5381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5383                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5384                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5385                 if (diffusescale > 0)
5386                         permutation |= SHADERPERMUTATION_DIFFUSE;
5387                 if (specularscale > 0)
5388                 {
5389                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5390                         if (r_shadow_glossexact.integer)
5391                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5392                 }
5393                 if (r_refdef.fogenabled)
5394                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5395                 if (rsurface.texture->colormapping)
5396                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5397                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5398                 {
5399                         if (r_shadow_usingshadowmaprect)
5400                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5401                         if (r_shadow_usingshadowmap2d)
5402                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5403                         if (r_shadow_usingshadowmapcube)
5404                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5405                         else if(r_shadow_shadowmapvsdct)
5406                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5407
5408                         if (r_shadow_shadowmapsampler)
5409                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5410                         if (r_shadow_shadowmappcf > 1)
5411                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5412                         else if (r_shadow_shadowmappcf)
5413                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5414                 }
5415                 if (rsurface.texture->reflectmasktexture)
5416                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5417                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5418                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5419         }
5420         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5421         {
5422                 if (r_glsl_offsetmapping.integer)
5423                 {
5424                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5425                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5426                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5427                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5428                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5429                         {
5430                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5431                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5432                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5433                         }
5434                 }
5435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5436                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5437                 // unshaded geometry (fullbright or ambient model lighting)
5438                 mode = SHADERMODE_FLATCOLOR;
5439                 ambientscale = diffusescale = specularscale = 0;
5440                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5441                         permutation |= SHADERPERMUTATION_GLOW;
5442                 if (r_refdef.fogenabled)
5443                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5444                 if (rsurface.texture->colormapping)
5445                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5446                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5447                 {
5448                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5449                         if (r_shadow_usingshadowmaprect)
5450                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5451                         if (r_shadow_usingshadowmap2d)
5452                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5453
5454                         if (r_shadow_shadowmapsampler)
5455                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5456                         if (r_shadow_shadowmappcf > 1)
5457                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5458                         else if (r_shadow_shadowmappcf)
5459                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5460                 }
5461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5462                         permutation |= SHADERPERMUTATION_REFLECTION;
5463                 if (rsurface.texture->reflectmasktexture)
5464                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5465                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5466                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5467         }
5468         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5469         {
5470                 if (r_glsl_offsetmapping.integer)
5471                 {
5472                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5473                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5474                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5475                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5476                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5477                         {
5478                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5479                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5480                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5481                         }
5482                 }
5483                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5484                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5485                 // directional model lighting
5486                 mode = SHADERMODE_LIGHTDIRECTION;
5487                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5488                         permutation |= SHADERPERMUTATION_GLOW;
5489                 permutation |= SHADERPERMUTATION_DIFFUSE;
5490                 if (specularscale > 0)
5491                 {
5492                         permutation |= SHADERPERMUTATION_SPECULAR;
5493                         if (r_shadow_glossexact.integer)
5494                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5495                 }
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 (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5518                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5519                 if (rsurface.texture->reflectmasktexture)
5520                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5521                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5522                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5523         }
5524         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5525         {
5526                 if (r_glsl_offsetmapping.integer)
5527                 {
5528                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5529                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5530                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5531                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5532                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5533                         {
5534                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5535                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5536                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5537                         }
5538                 }
5539                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5540                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5541                 // ambient model lighting
5542                 mode = SHADERMODE_LIGHTDIRECTION;
5543                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5544                         permutation |= SHADERPERMUTATION_GLOW;
5545                 if (r_refdef.fogenabled)
5546                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5547                 if (rsurface.texture->colormapping)
5548                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5549                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5550                 {
5551                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5552                         if (r_shadow_usingshadowmaprect)
5553                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5554                         if (r_shadow_usingshadowmap2d)
5555                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5556
5557                         if (r_shadow_shadowmapsampler)
5558                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5559                         if (r_shadow_shadowmappcf > 1)
5560                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5561                         else if (r_shadow_shadowmappcf)
5562                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5563                 }
5564                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5565                         permutation |= SHADERPERMUTATION_REFLECTION;
5566                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5567                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5568                 if (rsurface.texture->reflectmasktexture)
5569                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5570                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5571                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5572         }
5573         else
5574         {
5575                 if (r_glsl_offsetmapping.integer)
5576                 {
5577                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5578                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5579                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5580                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5581                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5582                         {
5583                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5584                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5585                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5586                         }
5587                 }
5588                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5589                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5590                 // lightmapped wall
5591                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5592                         permutation |= SHADERPERMUTATION_GLOW;
5593                 if (r_refdef.fogenabled)
5594                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5595                 if (rsurface.texture->colormapping)
5596                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5597                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5598                 {
5599                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5600                         if (r_shadow_usingshadowmaprect)
5601                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5602                         if (r_shadow_usingshadowmap2d)
5603                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5604
5605                         if (r_shadow_shadowmapsampler)
5606                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5607                         if (r_shadow_shadowmappcf > 1)
5608                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5609                         else if (r_shadow_shadowmappcf)
5610                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5611                 }
5612                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5613                         permutation |= SHADERPERMUTATION_REFLECTION;
5614                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5615                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5616                 if (rsurface.texture->reflectmasktexture)
5617                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5618                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5619                 {
5620                         // deluxemapping (light direction texture)
5621                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5622                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5623                         else
5624                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5625                         permutation |= SHADERPERMUTATION_DIFFUSE;
5626                         if (specularscale > 0)
5627                         {
5628                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5629                                 if (r_shadow_glossexact.integer)
5630                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5631                         }
5632                 }
5633                 else if (r_glsl_deluxemapping.integer >= 2)
5634                 {
5635                         // fake deluxemapping (uniform light direction in tangentspace)
5636                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5637                         permutation |= SHADERPERMUTATION_DIFFUSE;
5638                         if (specularscale > 0)
5639                         {
5640                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5641                                 if (r_shadow_glossexact.integer)
5642                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5643                         }
5644                 }
5645                 else if (rsurface.uselightmaptexture)
5646                 {
5647                         // ordinary lightmapping (q1bsp, q3bsp)
5648                         mode = SHADERMODE_LIGHTMAP;
5649                 }
5650                 else
5651                 {
5652                         // ordinary vertex coloring (q3bsp)
5653                         mode = SHADERMODE_VERTEXCOLOR;
5654                 }
5655                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5656                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5657         }
5658         switch(vid.renderpath)
5659         {
5660         case RENDERPATH_D3D9:
5661 #ifdef SUPPORTD3D
5662                 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);
5663                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5664                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5665                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5666                 if (mode == SHADERMODE_LIGHTSOURCE)
5667                 {
5668                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5669                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5670                 }
5671                 else
5672                 {
5673                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5674                         {
5675                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5676                         }
5677                 }
5678                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5679                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5680                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5681                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5682                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5683
5684                 if (mode == SHADERMODE_LIGHTSOURCE)
5685                 {
5686                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5687                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5688                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
5689                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
5690                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5691
5692                         // additive passes are only darkened by fog, not tinted
5693                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5694                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5695                 }
5696                 else
5697                 {
5698                         if (mode == SHADERMODE_FLATCOLOR)
5699                         {
5700                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
5701                         }
5702                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5703                         {
5704                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
5705                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
5706                                 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);
5707                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
5708                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5709                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5710                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5711                         }
5712                         else
5713                         {
5714                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
5715                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5716                                 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);
5717                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5718                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5719                         }
5720                         // additive passes are only darkened by fog, not tinted
5721                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5722                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5723                         else
5724                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5725                         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);
5726                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5727                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5728                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5729                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5730                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5731                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5732                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5733                 }
5734                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5735                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5736                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5737                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5738                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5739                 if (rsurface.texture->pantstexture)
5740                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5741                 else
5742                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5743                 if (rsurface.texture->shirttexture)
5744                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5745                 else
5746                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5747                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5748                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5749                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5750                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5751                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5752                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5753                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5754
5755                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5756                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5757                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5758                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5759                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5760                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5761                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5762                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5763                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5764                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5765                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5766                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5767                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5768                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5769                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5770                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5771                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5772                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5773                 {
5774                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5775                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5776                         R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5777                 }
5778                 else
5779                 {
5780                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5781                 }
5782 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5783 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5784                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5785                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5786                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5787                 {
5788                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5789                         if (rsurface.rtlight)
5790                         {
5791                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5792                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5793                         }
5794                 }
5795 #endif
5796                 break;
5797         case RENDERPATH_D3D10:
5798                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5799                 break;
5800         case RENDERPATH_D3D11:
5801                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5802                 break;
5803         case RENDERPATH_GL20:
5804                 if (gl_mesh_separatearrays.integer)
5805                 {
5806                         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);
5807                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5808                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5809                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5810                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5811                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5812                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5813                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5814                 }
5815                 else
5816                 {
5817                         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);
5818                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5819                 }
5820                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5821                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5822                 if (mode == SHADERMODE_LIGHTSOURCE)
5823                 {
5824                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5825                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5826                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5827                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
5828                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
5829                         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);
5830         
5831                         // additive passes are only darkened by fog, not tinted
5832                         if (r_glsl_permutation->loc_FogColor >= 0)
5833                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5834                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5835                 }
5836                 else
5837                 {
5838                         if (mode == SHADERMODE_FLATCOLOR)
5839                         {
5840                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
5841                         }
5842                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5843                         {
5844                                 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) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
5845                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
5846                                 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);
5847                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
5848                                 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);
5849                                 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]);
5850                                 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]);
5851                         }
5852                         else
5853                         {
5854                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
5855                                 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]);
5856                                 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);
5857                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5858                                 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);
5859                         }
5860                         // additive passes are only darkened by fog, not tinted
5861                         if (r_glsl_permutation->loc_FogColor >= 0)
5862                         {
5863                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5864                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5865                                 else
5866                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5867                         }
5868                         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);
5869                         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]);
5870                         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]);
5871                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5872                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5873                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5874                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5875                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5876                 }
5877                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5878                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5879                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5880                 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]);
5881                 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]);
5882
5883                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5884                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5885                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5886                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5887                 {
5888                         if (rsurface.texture->pantstexture)
5889                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5890                         else
5891                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5892                 }
5893                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5894                 {
5895                         if (rsurface.texture->shirttexture)
5896                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5897                         else
5898                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5899                 }
5900                 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]);
5901                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5902                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5903                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5904                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5905                 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]);
5906                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5907
5908         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5909         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5910         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5911                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5912                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5913                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5914                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5915                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5916                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5917                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5918                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5919                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5920                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5921                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5922                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5923                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5924                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5925                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5926                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5927                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5928                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5929                 {
5930                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5931                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5932                         R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5933                 }
5934                 else
5935                 {
5936                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5937                 }
5938 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5939 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5940                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5941                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5942                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5943                 {
5944                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5945                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5946                         if (rsurface.rtlight)
5947                         {
5948                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5949                                 if (r_shadow_usingshadowmapcube)
5950                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5951                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5952                         }
5953                 }
5954                 CHECKGLERROR
5955                 break;
5956         case RENDERPATH_CGGL:
5957 #ifdef SUPPORTCG
5958                 if (gl_mesh_separatearrays.integer)
5959                 {
5960                         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);
5961                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5962                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5963                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5964                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5965                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5966                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5967                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5968                 }
5969                 else
5970                 {
5971                         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);
5972                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5973                 }
5974                 R_SetupShader_SetPermutationCG(mode, permutation);
5975                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5976                 if (mode == SHADERMODE_LIGHTSOURCE)
5977                 {
5978                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5979                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5980                 }
5981                 else
5982                 {
5983                         if (mode == SHADERMODE_LIGHTDIRECTION)
5984                         {
5985                                 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
5986                         }
5987                 }
5988                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5989                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5990                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5991                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5992                 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
5993                 CHECKGLERROR
5994
5995                 if (mode == SHADERMODE_LIGHTSOURCE)
5996                 {
5997                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5998                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5999                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
6000                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
6001                         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
6002
6003                         // additive passes are only darkened by fog, not tinted
6004                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6005                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6006                 }
6007                 else
6008                 {
6009                         if (mode == SHADERMODE_FLATCOLOR)
6010                         {
6011                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
6012                         }
6013                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6014                         {
6015                                 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) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
6016                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
6017                                 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
6018                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6019                                 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
6020                                 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
6021                                 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
6022                         }
6023                         else
6024                         {
6025                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
6026                                 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
6027                                 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
6028                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6029                                 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
6030                         }
6031                         // additive passes are only darkened by fog, not tinted
6032                         if (r_cg_permutation->fp_FogColor)
6033                         {
6034                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6035                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6036                                 else
6037                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6038                                 CHECKCGERROR
6039                         }
6040                         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
6041                         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
6042                         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
6043                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6044                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6045                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6046                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6047                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6048                 }
6049                 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
6050                 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
6051                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6052                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6053                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6054                 if (r_cg_permutation->fp_Color_Pants)
6055                 {
6056                         if (rsurface.texture->pantstexture)
6057                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6058                         else
6059                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6060                         CHECKCGERROR
6061                 }
6062                 if (r_cg_permutation->fp_Color_Shirt)
6063                 {
6064                         if (rsurface.texture->shirttexture)
6065                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6066                         else
6067                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6068                         CHECKCGERROR
6069                 }
6070                 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
6071                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6072                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6073                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6074                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6075                 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
6076                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6077
6078         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6079         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6080         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6081                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6082                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6083                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6084                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6085                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6086                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6087                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6088                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6089                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6090                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6091                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6092                 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
6093                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6094                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6095                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6096                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6097                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6098                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6099                 {
6100                         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
6101                         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
6102                         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
6103                 }
6104                 else
6105                 {
6106                         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
6107                 }
6108                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6109                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6110                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6111                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6112                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6113                 {
6114                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6115                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6116                         if (rsurface.rtlight)
6117                         {
6118                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6119                                 if (r_shadow_usingshadowmapcube)
6120                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6121                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6122                         }
6123                 }
6124
6125                 CHECKGLERROR
6126 #endif
6127                 break;
6128         case RENDERPATH_GL13:
6129         case RENDERPATH_GL11:
6130                 break;
6131         }
6132 }
6133
6134 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6135 {
6136         // select a permutation of the lighting shader appropriate to this
6137         // combination of texture, entity, light source, and fogging, only use the
6138         // minimum features necessary to avoid wasting rendering time in the
6139         // fragment shader on features that are not being used
6140         unsigned int permutation = 0;
6141         unsigned int mode = 0;
6142         const float *lightcolorbase = rtlight->currentcolor;
6143         float ambientscale = rtlight->ambientscale;
6144         float diffusescale = rtlight->diffusescale;
6145         float specularscale = rtlight->specularscale;
6146         // this is the location of the light in view space
6147         vec3_t viewlightorigin;
6148         // this transforms from view space (camera) to light space (cubemap)
6149         matrix4x4_t viewtolight;
6150         matrix4x4_t lighttoview;
6151         float viewtolight16f[16];
6152         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6153         // light source
6154         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6155         if (rtlight->currentcubemap != r_texture_whitecube)
6156                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6157         if (diffusescale > 0)
6158                 permutation |= SHADERPERMUTATION_DIFFUSE;
6159         if (specularscale > 0)
6160         {
6161                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6162                 if (r_shadow_glossexact.integer)
6163                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6164         }
6165         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6166         {
6167                 if (r_shadow_usingshadowmaprect)
6168                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6169                 if (r_shadow_usingshadowmap2d)
6170                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6171                 if (r_shadow_usingshadowmapcube)
6172                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6173                 else if(r_shadow_shadowmapvsdct)
6174                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6175
6176                 if (r_shadow_shadowmapsampler)
6177                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6178                 if (r_shadow_shadowmappcf > 1)
6179                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6180                 else if (r_shadow_shadowmappcf)
6181                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6182         }
6183         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6184         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6185         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6186         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6187         switch(vid.renderpath)
6188         {
6189         case RENDERPATH_D3D9:
6190 #ifdef SUPPORTD3D
6191                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6192                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6193                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6194                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6195                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6196                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6197                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6198                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6199                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6200                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6201                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6202
6203                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6204                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6205                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6206                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6207                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6208                 if (r_shadow_usingshadowmapcube)
6209                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6210                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6211                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6212 #endif
6213                 break;
6214         case RENDERPATH_D3D10:
6215                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6216                 break;
6217         case RENDERPATH_D3D11:
6218                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6219                 break;
6220         case RENDERPATH_GL20:
6221                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6222                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6223                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6224                 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);
6225                 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);
6226                 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);
6227                 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]);
6228                 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]);
6229                 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));
6230                 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]);
6231                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6232
6233                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6234                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6235                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6236                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6237                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6238                 if (r_shadow_usingshadowmapcube)
6239                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6240                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6241                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6242                 break;
6243         case RENDERPATH_CGGL:
6244 #ifdef SUPPORTCG
6245                 R_SetupShader_SetPermutationCG(mode, permutation);
6246                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6247                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6248                 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
6249                 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
6250                 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
6251                 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
6252                 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
6253                 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
6254                 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
6255                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6256
6257                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6258                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6259                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6260                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6261                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6262                 if (r_shadow_usingshadowmapcube)
6263                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6264                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6265                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6266 #endif
6267                 break;
6268         case RENDERPATH_GL13:
6269         case RENDERPATH_GL11:
6270                 break;
6271         }
6272 }
6273
6274 #define SKINFRAME_HASH 1024
6275
6276 typedef struct
6277 {
6278         int loadsequence; // incremented each level change
6279         memexpandablearray_t array;
6280         skinframe_t *hash[SKINFRAME_HASH];
6281 }
6282 r_skinframe_t;
6283 r_skinframe_t r_skinframe;
6284
6285 void R_SkinFrame_PrepareForPurge(void)
6286 {
6287         r_skinframe.loadsequence++;
6288         // wrap it without hitting zero
6289         if (r_skinframe.loadsequence >= 200)
6290                 r_skinframe.loadsequence = 1;
6291 }
6292
6293 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6294 {
6295         if (!skinframe)
6296                 return;
6297         // mark the skinframe as used for the purging code
6298         skinframe->loadsequence = r_skinframe.loadsequence;
6299 }
6300
6301 void R_SkinFrame_Purge(void)
6302 {
6303         int i;
6304         skinframe_t *s;
6305         for (i = 0;i < SKINFRAME_HASH;i++)
6306         {
6307                 for (s = r_skinframe.hash[i];s;s = s->next)
6308                 {
6309                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6310                         {
6311                                 if (s->merged == s->base)
6312                                         s->merged = NULL;
6313                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6314                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6315                                 R_PurgeTexture(s->merged);s->merged = NULL;
6316                                 R_PurgeTexture(s->base  );s->base   = NULL;
6317                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6318                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6319                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6320                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6321                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6322                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6323                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6324                                 s->loadsequence = 0;
6325                         }
6326                 }
6327         }
6328 }
6329
6330 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6331         skinframe_t *item;
6332         char basename[MAX_QPATH];
6333
6334         Image_StripImageExtension(name, basename, sizeof(basename));
6335
6336         if( last == NULL ) {
6337                 int hashindex;
6338                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6339                 item = r_skinframe.hash[hashindex];
6340         } else {
6341                 item = last->next;
6342         }
6343
6344         // linearly search through the hash bucket
6345         for( ; item ; item = item->next ) {
6346                 if( !strcmp( item->basename, basename ) ) {
6347                         return item;
6348                 }
6349         }
6350         return NULL;
6351 }
6352
6353 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6354 {
6355         skinframe_t *item;
6356         int hashindex;
6357         char basename[MAX_QPATH];
6358
6359         Image_StripImageExtension(name, basename, sizeof(basename));
6360
6361         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6362         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6363                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6364                         break;
6365
6366         if (!item) {
6367                 rtexture_t *dyntexture;
6368                 // check whether its a dynamic texture
6369                 dyntexture = CL_GetDynTexture( basename );
6370                 if (!add && !dyntexture)
6371                         return NULL;
6372                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6373                 memset(item, 0, sizeof(*item));
6374                 strlcpy(item->basename, basename, sizeof(item->basename));
6375                 item->base = dyntexture; // either NULL or dyntexture handle
6376                 item->textureflags = textureflags;
6377                 item->comparewidth = comparewidth;
6378                 item->compareheight = compareheight;
6379                 item->comparecrc = comparecrc;
6380                 item->next = r_skinframe.hash[hashindex];
6381                 r_skinframe.hash[hashindex] = item;
6382         }
6383         else if( item->base == NULL )
6384         {
6385                 rtexture_t *dyntexture;
6386                 // check whether its a dynamic texture
6387                 // 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]
6388                 dyntexture = CL_GetDynTexture( basename );
6389                 item->base = dyntexture; // either NULL or dyntexture handle
6390         }
6391
6392         R_SkinFrame_MarkUsed(item);
6393         return item;
6394 }
6395
6396 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6397         { \
6398                 unsigned long long avgcolor[5], wsum; \
6399                 int pix, comp, w; \
6400                 avgcolor[0] = 0; \
6401                 avgcolor[1] = 0; \
6402                 avgcolor[2] = 0; \
6403                 avgcolor[3] = 0; \
6404                 avgcolor[4] = 0; \
6405                 wsum = 0; \
6406                 for(pix = 0; pix < cnt; ++pix) \
6407                 { \
6408                         w = 0; \
6409                         for(comp = 0; comp < 3; ++comp) \
6410                                 w += getpixel; \
6411                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6412                         { \
6413                                 ++wsum; \
6414                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6415                                 w = getpixel; \
6416                                 for(comp = 0; comp < 3; ++comp) \
6417                                         avgcolor[comp] += getpixel * w; \
6418                                 avgcolor[3] += w; \
6419                         } \
6420                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6421                         avgcolor[4] += getpixel; \
6422                 } \
6423                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6424                         avgcolor[3] = 1; \
6425                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6426                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6427                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6428                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6429         }
6430
6431 extern cvar_t gl_picmip;
6432 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6433 {
6434         int j;
6435         unsigned char *pixels;
6436         unsigned char *bumppixels;
6437         unsigned char *basepixels = NULL;
6438         int basepixels_width = 0;
6439         int basepixels_height = 0;
6440         skinframe_t *skinframe;
6441         rtexture_t *ddsbase = NULL;
6442         qboolean ddshasalpha = false;
6443         float ddsavgcolor[4];
6444         char basename[MAX_QPATH];
6445         int miplevel = R_PicmipForFlags(textureflags);
6446         int savemiplevel = miplevel;
6447         int mymiplevel;
6448
6449         if (cls.state == ca_dedicated)
6450                 return NULL;
6451
6452         // return an existing skinframe if already loaded
6453         // if loading of the first image fails, don't make a new skinframe as it
6454         // would cause all future lookups of this to be missing
6455         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6456         if (skinframe && skinframe->base)
6457                 return skinframe;
6458
6459         Image_StripImageExtension(name, basename, sizeof(basename));
6460
6461         // check for DDS texture file first
6462         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6463         {
6464                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6465                 if (basepixels == NULL)
6466                         return NULL;
6467         }
6468
6469         // FIXME handle miplevel
6470
6471         if (developer_loading.integer)
6472                 Con_Printf("loading skin \"%s\"\n", name);
6473
6474         // we've got some pixels to store, so really allocate this new texture now
6475         if (!skinframe)
6476                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6477         skinframe->stain = NULL;
6478         skinframe->merged = NULL;
6479         skinframe->base = NULL;
6480         skinframe->pants = NULL;
6481         skinframe->shirt = NULL;
6482         skinframe->nmap = NULL;
6483         skinframe->gloss = NULL;
6484         skinframe->glow = NULL;
6485         skinframe->fog = NULL;
6486         skinframe->reflect = NULL;
6487         skinframe->hasalpha = false;
6488
6489         if (ddsbase)
6490         {
6491                 skinframe->base = ddsbase;
6492                 skinframe->hasalpha = ddshasalpha;
6493                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6494                 if (r_loadfog && skinframe->hasalpha)
6495                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6496                 //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]);
6497         }
6498         else
6499         {
6500                 basepixels_width = image_width;
6501                 basepixels_height = image_height;
6502                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6503                 if (textureflags & TEXF_ALPHA)
6504                 {
6505                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6506                         {
6507                                 if (basepixels[j] < 255)
6508                                 {
6509                                         skinframe->hasalpha = true;
6510                                         break;
6511                                 }
6512                         }
6513                         if (r_loadfog && skinframe->hasalpha)
6514                         {
6515                                 // has transparent pixels
6516                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6517                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6518                                 {
6519                                         pixels[j+0] = 255;
6520                                         pixels[j+1] = 255;
6521                                         pixels[j+2] = 255;
6522                                         pixels[j+3] = basepixels[j+3];
6523                                 }
6524                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6525                                 Mem_Free(pixels);
6526                         }
6527                 }
6528                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6529                 //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]);
6530                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6531                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
6532                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6533                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
6534         }
6535
6536         if (r_loaddds)
6537         {
6538                 mymiplevel = savemiplevel;
6539                 if (r_loadnormalmap)
6540                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, mymiplevel);
6541                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6542                 if (r_loadgloss)
6543                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6544                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6545                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6546                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6547         }
6548
6549         // _norm is the name used by tenebrae and has been adopted as standard
6550         if (r_loadnormalmap && skinframe->nmap == NULL)
6551         {
6552                 mymiplevel = savemiplevel;
6553                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6554                 {
6555                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6556                         Mem_Free(pixels);
6557                         pixels = NULL;
6558                 }
6559                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6560                 {
6561                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6562                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6563                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6564                         Mem_Free(pixels);
6565                         Mem_Free(bumppixels);
6566                 }
6567                 else if (r_shadow_bumpscale_basetexture.value > 0)
6568                 {
6569                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6570                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6571                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6572                         Mem_Free(pixels);
6573                 }
6574                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6575                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
6576         }
6577
6578         // _luma is supported only for tenebrae compatibility
6579         // _glow is the preferred name
6580         mymiplevel = savemiplevel;
6581         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))))
6582         {
6583                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6584                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6585                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
6586                 Mem_Free(pixels);pixels = NULL;
6587         }
6588
6589         mymiplevel = savemiplevel;
6590         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6591         {
6592                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6593                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6594                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
6595                 Mem_Free(pixels);
6596                 pixels = NULL;
6597         }
6598
6599         mymiplevel = savemiplevel;
6600         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6601         {
6602                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6603                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6604                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
6605                 Mem_Free(pixels);
6606                 pixels = NULL;
6607         }
6608
6609         mymiplevel = savemiplevel;
6610         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6611         {
6612                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6613                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6614                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
6615                 Mem_Free(pixels);
6616                 pixels = NULL;
6617         }
6618
6619         mymiplevel = savemiplevel;
6620         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6621         {
6622                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6624                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
6625                 Mem_Free(pixels);
6626                 pixels = NULL;
6627         }
6628
6629         if (basepixels)
6630                 Mem_Free(basepixels);
6631
6632         return skinframe;
6633 }
6634
6635 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6636 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6637 {
6638         int i;
6639         unsigned char *temp1, *temp2;
6640         skinframe_t *skinframe;
6641
6642         if (cls.state == ca_dedicated)
6643                 return NULL;
6644
6645         // if already loaded just return it, otherwise make a new skinframe
6646         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6647         if (skinframe && skinframe->base)
6648                 return skinframe;
6649
6650         skinframe->stain = NULL;
6651         skinframe->merged = NULL;
6652         skinframe->base = NULL;
6653         skinframe->pants = NULL;
6654         skinframe->shirt = NULL;
6655         skinframe->nmap = NULL;
6656         skinframe->gloss = NULL;
6657         skinframe->glow = NULL;
6658         skinframe->fog = NULL;
6659         skinframe->reflect = NULL;
6660         skinframe->hasalpha = false;
6661
6662         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6663         if (!skindata)
6664                 return NULL;
6665
6666         if (developer_loading.integer)
6667                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6668
6669         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6670         {
6671                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6672                 temp2 = temp1 + width * height * 4;
6673                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6674                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
6675                 Mem_Free(temp1);
6676         }
6677         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
6678         if (textureflags & TEXF_ALPHA)
6679         {
6680                 for (i = 3;i < width * height * 4;i += 4)
6681                 {
6682                         if (skindata[i] < 255)
6683                         {
6684                                 skinframe->hasalpha = true;
6685                                 break;
6686                         }
6687                 }
6688                 if (r_loadfog && skinframe->hasalpha)
6689                 {
6690                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6691                         memcpy(fogpixels, skindata, width * height * 4);
6692                         for (i = 0;i < width * height * 4;i += 4)
6693                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6694                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
6695                         Mem_Free(fogpixels);
6696                 }
6697         }
6698
6699         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6700         //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]);
6701
6702         return skinframe;
6703 }
6704
6705 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6706 {
6707         int i;
6708         int featuresmask;
6709         skinframe_t *skinframe;
6710
6711         if (cls.state == ca_dedicated)
6712                 return NULL;
6713
6714         // if already loaded just return it, otherwise make a new skinframe
6715         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6716         if (skinframe && skinframe->base)
6717                 return skinframe;
6718
6719         skinframe->stain = NULL;
6720         skinframe->merged = NULL;
6721         skinframe->base = NULL;
6722         skinframe->pants = NULL;
6723         skinframe->shirt = NULL;
6724         skinframe->nmap = NULL;
6725         skinframe->gloss = NULL;
6726         skinframe->glow = NULL;
6727         skinframe->fog = NULL;
6728         skinframe->reflect = NULL;
6729         skinframe->hasalpha = false;
6730
6731         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6732         if (!skindata)
6733                 return NULL;
6734
6735         if (developer_loading.integer)
6736                 Con_Printf("loading quake skin \"%s\"\n", name);
6737
6738         // 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)
6739         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6740         memcpy(skinframe->qpixels, skindata, width*height);
6741         skinframe->qwidth = width;
6742         skinframe->qheight = height;
6743
6744         featuresmask = 0;
6745         for (i = 0;i < width * height;i++)
6746                 featuresmask |= palette_featureflags[skindata[i]];
6747
6748         skinframe->hasalpha = false;
6749         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6750         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6751         skinframe->qgeneratemerged = true;
6752         skinframe->qgeneratebase = skinframe->qhascolormapping;
6753         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6754
6755         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6756         //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]);
6757
6758         return skinframe;
6759 }
6760
6761 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6762 {
6763         int width;
6764         int height;
6765         unsigned char *skindata;
6766
6767         if (!skinframe->qpixels)
6768                 return;
6769
6770         if (!skinframe->qhascolormapping)
6771                 colormapped = false;
6772
6773         if (colormapped)
6774         {
6775                 if (!skinframe->qgeneratebase)
6776                         return;
6777         }
6778         else
6779         {
6780                 if (!skinframe->qgeneratemerged)
6781                         return;
6782         }
6783
6784         width = skinframe->qwidth;
6785         height = skinframe->qheight;
6786         skindata = skinframe->qpixels;
6787
6788         if (skinframe->qgeneratenmap)
6789         {
6790                 unsigned char *temp1, *temp2;
6791                 skinframe->qgeneratenmap = false;
6792                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6793                 temp2 = temp1 + width * height * 4;
6794                 // use either a custom palette or the quake palette
6795                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6796                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6797                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
6798                 Mem_Free(temp1);
6799         }
6800
6801         if (skinframe->qgenerateglow)
6802         {
6803                 skinframe->qgenerateglow = false;
6804                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6805         }
6806
6807         if (colormapped)
6808         {
6809                 skinframe->qgeneratebase = false;
6810                 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);
6811                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6812                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6813         }
6814         else
6815         {
6816                 skinframe->qgeneratemerged = false;
6817                 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);
6818         }
6819
6820         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6821         {
6822                 Mem_Free(skinframe->qpixels);
6823                 skinframe->qpixels = NULL;
6824         }
6825 }
6826
6827 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)
6828 {
6829         int i;
6830         skinframe_t *skinframe;
6831
6832         if (cls.state == ca_dedicated)
6833                 return NULL;
6834
6835         // if already loaded just return it, otherwise make a new skinframe
6836         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6837         if (skinframe && skinframe->base)
6838                 return skinframe;
6839
6840         skinframe->stain = NULL;
6841         skinframe->merged = NULL;
6842         skinframe->base = NULL;
6843         skinframe->pants = NULL;
6844         skinframe->shirt = NULL;
6845         skinframe->nmap = NULL;
6846         skinframe->gloss = NULL;
6847         skinframe->glow = NULL;
6848         skinframe->fog = NULL;
6849         skinframe->reflect = NULL;
6850         skinframe->hasalpha = false;
6851
6852         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6853         if (!skindata)
6854                 return NULL;
6855
6856         if (developer_loading.integer)
6857                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6858
6859         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette);
6860         if (textureflags & TEXF_ALPHA)
6861         {
6862                 for (i = 0;i < width * height;i++)
6863                 {
6864                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6865                         {
6866                                 skinframe->hasalpha = true;
6867                                 break;
6868                         }
6869                 }
6870                 if (r_loadfog && skinframe->hasalpha)
6871                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, alphapalette);
6872         }
6873
6874         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6875         //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]);
6876
6877         return skinframe;
6878 }
6879
6880 skinframe_t *R_SkinFrame_LoadMissing(void)
6881 {
6882         skinframe_t *skinframe;
6883
6884         if (cls.state == ca_dedicated)
6885                 return NULL;
6886
6887         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6888         skinframe->stain = NULL;
6889         skinframe->merged = NULL;
6890         skinframe->base = NULL;
6891         skinframe->pants = NULL;
6892         skinframe->shirt = NULL;
6893         skinframe->nmap = NULL;
6894         skinframe->gloss = NULL;
6895         skinframe->glow = NULL;
6896         skinframe->fog = NULL;
6897         skinframe->reflect = NULL;
6898         skinframe->hasalpha = false;
6899
6900         skinframe->avgcolor[0] = rand() / RAND_MAX;
6901         skinframe->avgcolor[1] = rand() / RAND_MAX;
6902         skinframe->avgcolor[2] = rand() / RAND_MAX;
6903         skinframe->avgcolor[3] = 1;
6904
6905         return skinframe;
6906 }
6907
6908 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6909 typedef struct suffixinfo_s
6910 {
6911         char *suffix;
6912         qboolean flipx, flipy, flipdiagonal;
6913 }
6914 suffixinfo_t;
6915 static suffixinfo_t suffix[3][6] =
6916 {
6917         {
6918                 {"px",   false, false, false},
6919                 {"nx",   false, false, false},
6920                 {"py",   false, false, false},
6921                 {"ny",   false, false, false},
6922                 {"pz",   false, false, false},
6923                 {"nz",   false, false, false}
6924         },
6925         {
6926                 {"posx", false, false, false},
6927                 {"negx", false, false, false},
6928                 {"posy", false, false, false},
6929                 {"negy", false, false, false},
6930                 {"posz", false, false, false},
6931                 {"negz", false, false, false}
6932         },
6933         {
6934                 {"rt",    true, false,  true},
6935                 {"lf",   false,  true,  true},
6936                 {"ft",    true,  true, false},
6937                 {"bk",   false, false, false},
6938                 {"up",    true, false,  true},
6939                 {"dn",    true, false,  true}
6940         }
6941 };
6942
6943 static int componentorder[4] = {0, 1, 2, 3};
6944
6945 rtexture_t *R_LoadCubemap(const char *basename)
6946 {
6947         int i, j, cubemapsize;
6948         unsigned char *cubemappixels, *image_buffer;
6949         rtexture_t *cubemaptexture;
6950         char name[256];
6951         // must start 0 so the first loadimagepixels has no requested width/height
6952         cubemapsize = 0;
6953         cubemappixels = NULL;
6954         cubemaptexture = NULL;
6955         // keep trying different suffix groups (posx, px, rt) until one loads
6956         for (j = 0;j < 3 && !cubemappixels;j++)
6957         {
6958                 // load the 6 images in the suffix group
6959                 for (i = 0;i < 6;i++)
6960                 {
6961                         // generate an image name based on the base and and suffix
6962                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6963                         // load it
6964                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6965                         {
6966                                 // an image loaded, make sure width and height are equal
6967                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6968                                 {
6969                                         // if this is the first image to load successfully, allocate the cubemap memory
6970                                         if (!cubemappixels && image_width >= 1)
6971                                         {
6972                                                 cubemapsize = image_width;
6973                                                 // note this clears to black, so unavailable sides are black
6974                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6975                                         }
6976                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6977                                         if (cubemappixels)
6978                                                 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);
6979                                 }
6980                                 else
6981                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6982                                 // free the image
6983                                 Mem_Free(image_buffer);
6984                         }
6985                 }
6986         }
6987         // if a cubemap loaded, upload it
6988         if (cubemappixels)
6989         {
6990                 if (developer_loading.integer)
6991                         Con_Printf("loading cubemap \"%s\"\n", basename);
6992
6993                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6994                 Mem_Free(cubemappixels);
6995         }
6996         else
6997         {
6998                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6999                 if (developer_loading.integer)
7000                 {
7001                         Con_Printf("(tried tried images ");
7002                         for (j = 0;j < 3;j++)
7003                                 for (i = 0;i < 6;i++)
7004                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7005                         Con_Print(" and was unable to find any of them).\n");
7006                 }
7007         }
7008         return cubemaptexture;
7009 }
7010
7011 rtexture_t *R_GetCubemap(const char *basename)
7012 {
7013         int i;
7014         for (i = 0;i < r_texture_numcubemaps;i++)
7015                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7016                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7017         if (i >= MAX_CUBEMAPS)
7018                 return r_texture_whitecube;
7019         r_texture_numcubemaps++;
7020         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7021         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7022         return r_texture_cubemaps[i].texture;
7023 }
7024
7025 void R_FreeCubemaps(void)
7026 {
7027         int i;
7028         for (i = 0;i < r_texture_numcubemaps;i++)
7029         {
7030                 if (developer_loading.integer)
7031                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7032                 if (r_texture_cubemaps[i].texture)
7033                         R_FreeTexture(r_texture_cubemaps[i].texture);
7034         }
7035         r_texture_numcubemaps = 0;
7036 }
7037
7038 void R_Main_FreeViewCache(void)
7039 {
7040         if (r_refdef.viewcache.entityvisible)
7041                 Mem_Free(r_refdef.viewcache.entityvisible);
7042         if (r_refdef.viewcache.world_pvsbits)
7043                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7044         if (r_refdef.viewcache.world_leafvisible)
7045                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7046         if (r_refdef.viewcache.world_surfacevisible)
7047                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7048         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7049 }
7050
7051 void R_Main_ResizeViewCache(void)
7052 {
7053         int numentities = r_refdef.scene.numentities;
7054         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7055         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7056         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7057         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7058         if (r_refdef.viewcache.maxentities < numentities)
7059         {
7060                 r_refdef.viewcache.maxentities = numentities;
7061                 if (r_refdef.viewcache.entityvisible)
7062                         Mem_Free(r_refdef.viewcache.entityvisible);
7063                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7064         }
7065         if (r_refdef.viewcache.world_numclusters != numclusters)
7066         {
7067                 r_refdef.viewcache.world_numclusters = numclusters;
7068                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7069                 if (r_refdef.viewcache.world_pvsbits)
7070                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7071                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7072         }
7073         if (r_refdef.viewcache.world_numleafs != numleafs)
7074         {
7075                 r_refdef.viewcache.world_numleafs = numleafs;
7076                 if (r_refdef.viewcache.world_leafvisible)
7077                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7078                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7079         }
7080         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7081         {
7082                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7083                 if (r_refdef.viewcache.world_surfacevisible)
7084                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7085                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7086         }
7087 }
7088
7089 extern rtexture_t *loadingscreentexture;
7090 void gl_main_start(void)
7091 {
7092         loadingscreentexture = NULL;
7093         r_texture_blanknormalmap = NULL;
7094         r_texture_white = NULL;
7095         r_texture_grey128 = NULL;
7096         r_texture_black = NULL;
7097         r_texture_whitecube = NULL;
7098         r_texture_normalizationcube = NULL;
7099         r_texture_fogattenuation = NULL;
7100         r_texture_fogheighttexture = NULL;
7101         r_texture_gammaramps = NULL;
7102         r_texture_numcubemaps = 0;
7103
7104         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7105         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7106
7107         switch(vid.renderpath)
7108         {
7109         case RENDERPATH_GL20:
7110         case RENDERPATH_CGGL:
7111         case RENDERPATH_D3D9:
7112         case RENDERPATH_D3D10:
7113         case RENDERPATH_D3D11:
7114                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7115                 Cvar_SetValueQuick(&gl_combine, 1);
7116                 Cvar_SetValueQuick(&r_glsl, 1);
7117                 r_loadnormalmap = true;
7118                 r_loadgloss = true;
7119                 r_loadfog = false;
7120                 break;
7121         case RENDERPATH_GL13:
7122                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7123                 Cvar_SetValueQuick(&gl_combine, 1);
7124                 Cvar_SetValueQuick(&r_glsl, 0);
7125                 r_loadnormalmap = false;
7126                 r_loadgloss = false;
7127                 r_loadfog = true;
7128                 break;
7129         case RENDERPATH_GL11:
7130                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7131                 Cvar_SetValueQuick(&gl_combine, 0);
7132                 Cvar_SetValueQuick(&r_glsl, 0);
7133                 r_loadnormalmap = false;
7134                 r_loadgloss = false;
7135                 r_loadfog = true;
7136                 break;
7137         }
7138
7139         R_AnimCache_Free();
7140         R_FrameData_Reset();
7141
7142         r_numqueries = 0;
7143         r_maxqueries = 0;
7144         memset(r_queries, 0, sizeof(r_queries));
7145
7146         r_qwskincache = NULL;
7147         r_qwskincache_size = 0;
7148
7149         // set up r_skinframe loading system for textures
7150         memset(&r_skinframe, 0, sizeof(r_skinframe));
7151         r_skinframe.loadsequence = 1;
7152         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7153
7154         r_main_texturepool = R_AllocTexturePool();
7155         R_BuildBlankTextures();
7156         R_BuildNoTexture();
7157         if (vid.support.arb_texture_cube_map)
7158         {
7159                 R_BuildWhiteCube();
7160                 R_BuildNormalizationCube();
7161         }
7162         r_texture_fogattenuation = NULL;
7163         r_texture_fogheighttexture = NULL;
7164         r_texture_gammaramps = NULL;
7165         //r_texture_fogintensity = NULL;
7166         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7167         memset(&r_waterstate, 0, sizeof(r_waterstate));
7168         r_glsl_permutation = NULL;
7169         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7170         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7171         glslshaderstring = NULL;
7172 #ifdef SUPPORTCG
7173         r_cg_permutation = NULL;
7174         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7175         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7176         cgshaderstring = NULL;
7177 #endif
7178 #ifdef SUPPORTD3D
7179         r_hlsl_permutation = NULL;
7180         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7181         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7182         hlslshaderstring = NULL;
7183 #endif
7184         memset(&r_svbsp, 0, sizeof (r_svbsp));
7185
7186         r_refdef.fogmasktable_density = 0;
7187 }
7188
7189 void gl_main_shutdown(void)
7190 {
7191         R_AnimCache_Free();
7192         R_FrameData_Reset();
7193
7194         R_Main_FreeViewCache();
7195
7196         switch(vid.renderpath)
7197         {
7198         case RENDERPATH_GL11:
7199         case RENDERPATH_GL13:
7200         case RENDERPATH_GL20:
7201         case RENDERPATH_CGGL:
7202                 if (r_maxqueries)
7203                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7204                 break;
7205         case RENDERPATH_D3D9:
7206                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7207                 break;
7208         case RENDERPATH_D3D10:
7209                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7210                 break;
7211         case RENDERPATH_D3D11:
7212                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7213                 break;
7214         }
7215
7216         r_numqueries = 0;
7217         r_maxqueries = 0;
7218         memset(r_queries, 0, sizeof(r_queries));
7219
7220         r_qwskincache = NULL;
7221         r_qwskincache_size = 0;
7222
7223         // clear out the r_skinframe state
7224         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7225         memset(&r_skinframe, 0, sizeof(r_skinframe));
7226
7227         if (r_svbsp.nodes)
7228                 Mem_Free(r_svbsp.nodes);
7229         memset(&r_svbsp, 0, sizeof (r_svbsp));
7230         R_FreeTexturePool(&r_main_texturepool);
7231         loadingscreentexture = NULL;
7232         r_texture_blanknormalmap = NULL;
7233         r_texture_white = NULL;
7234         r_texture_grey128 = NULL;
7235         r_texture_black = NULL;
7236         r_texture_whitecube = NULL;
7237         r_texture_normalizationcube = NULL;
7238         r_texture_fogattenuation = NULL;
7239         r_texture_fogheighttexture = NULL;
7240         r_texture_gammaramps = NULL;
7241         r_texture_numcubemaps = 0;
7242         //r_texture_fogintensity = NULL;
7243         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7244         memset(&r_waterstate, 0, sizeof(r_waterstate));
7245         R_GLSL_Restart_f();
7246 }
7247
7248 extern void CL_ParseEntityLump(char *entitystring);
7249 void gl_main_newmap(void)
7250 {
7251         // FIXME: move this code to client
7252         char *entities, entname[MAX_QPATH];
7253         if (r_qwskincache)
7254                 Mem_Free(r_qwskincache);
7255         r_qwskincache = NULL;
7256         r_qwskincache_size = 0;
7257         if (cl.worldmodel)
7258         {
7259                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7260                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7261                 {
7262                         CL_ParseEntityLump(entities);
7263                         Mem_Free(entities);
7264                         return;
7265                 }
7266                 if (cl.worldmodel->brush.entities)
7267                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7268         }
7269         R_Main_FreeViewCache();
7270
7271         R_FrameData_Reset();
7272 }
7273
7274 void GL_Main_Init(void)
7275 {
7276         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7277
7278         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7279         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7280         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7281         if (gamemode == GAME_NEHAHRA)
7282         {
7283                 Cvar_RegisterVariable (&gl_fogenable);
7284                 Cvar_RegisterVariable (&gl_fogdensity);
7285                 Cvar_RegisterVariable (&gl_fogred);
7286                 Cvar_RegisterVariable (&gl_foggreen);
7287                 Cvar_RegisterVariable (&gl_fogblue);
7288                 Cvar_RegisterVariable (&gl_fogstart);
7289                 Cvar_RegisterVariable (&gl_fogend);
7290                 Cvar_RegisterVariable (&gl_skyclip);
7291         }
7292         Cvar_RegisterVariable(&r_motionblur);
7293         Cvar_RegisterVariable(&r_motionblur_maxblur);
7294         Cvar_RegisterVariable(&r_motionblur_bmin);
7295         Cvar_RegisterVariable(&r_motionblur_vmin);
7296         Cvar_RegisterVariable(&r_motionblur_vmax);
7297         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7298         Cvar_RegisterVariable(&r_motionblur_randomize);
7299         Cvar_RegisterVariable(&r_damageblur);
7300         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7301         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7302         Cvar_RegisterVariable(&r_equalize_entities_by);
7303         Cvar_RegisterVariable(&r_equalize_entities_to);
7304         Cvar_RegisterVariable(&r_depthfirst);
7305         Cvar_RegisterVariable(&r_useinfinitefarclip);
7306         Cvar_RegisterVariable(&r_farclip_base);
7307         Cvar_RegisterVariable(&r_farclip_world);
7308         Cvar_RegisterVariable(&r_nearclip);
7309         Cvar_RegisterVariable(&r_showbboxes);
7310         Cvar_RegisterVariable(&r_showsurfaces);
7311         Cvar_RegisterVariable(&r_showtris);
7312         Cvar_RegisterVariable(&r_shownormals);
7313         Cvar_RegisterVariable(&r_showlighting);
7314         Cvar_RegisterVariable(&r_showshadowvolumes);
7315         Cvar_RegisterVariable(&r_showcollisionbrushes);
7316         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7317         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7318         Cvar_RegisterVariable(&r_showdisabledepthtest);
7319         Cvar_RegisterVariable(&r_drawportals);
7320         Cvar_RegisterVariable(&r_drawentities);
7321         Cvar_RegisterVariable(&r_draw2d);
7322         Cvar_RegisterVariable(&r_drawworld);
7323         Cvar_RegisterVariable(&r_cullentities_trace);
7324         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7325         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7326         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7327         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7328         Cvar_RegisterVariable(&r_drawviewmodel);
7329         Cvar_RegisterVariable(&r_drawexteriormodel);
7330         Cvar_RegisterVariable(&r_speeds);
7331         Cvar_RegisterVariable(&r_fullbrights);
7332         Cvar_RegisterVariable(&r_wateralpha);
7333         Cvar_RegisterVariable(&r_dynamic);
7334         Cvar_RegisterVariable(&r_fullbright);
7335         Cvar_RegisterVariable(&r_shadows);
7336         Cvar_RegisterVariable(&r_shadows_darken);
7337         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7338         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7339         Cvar_RegisterVariable(&r_shadows_throwdistance);
7340         Cvar_RegisterVariable(&r_shadows_throwdirection);
7341         Cvar_RegisterVariable(&r_shadows_focus);
7342         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7343         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7344         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7345         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7346         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7347         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7348         Cvar_RegisterVariable(&r_fog_exp2);
7349         Cvar_RegisterVariable(&r_drawfog);
7350         Cvar_RegisterVariable(&r_transparentdepthmasking);
7351         Cvar_RegisterVariable(&r_texture_dds_load);
7352         Cvar_RegisterVariable(&r_texture_dds_save);
7353         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7354         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7355         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7356         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7357         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7358         Cvar_RegisterVariable(&r_textureunits);
7359         Cvar_RegisterVariable(&gl_combine);
7360         Cvar_RegisterVariable(&r_glsl);
7361         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7362         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7363         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7364         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7365         Cvar_RegisterVariable(&r_glsl_postprocess);
7366         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7367         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7368         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7369         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7370         Cvar_RegisterVariable(&r_water);
7371         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7372         Cvar_RegisterVariable(&r_water_clippingplanebias);
7373         Cvar_RegisterVariable(&r_water_refractdistort);
7374         Cvar_RegisterVariable(&r_water_reflectdistort);
7375         Cvar_RegisterVariable(&r_lerpsprites);
7376         Cvar_RegisterVariable(&r_lerpmodels);
7377         Cvar_RegisterVariable(&r_lerplightstyles);
7378         Cvar_RegisterVariable(&r_waterscroll);
7379         Cvar_RegisterVariable(&r_bloom);
7380         Cvar_RegisterVariable(&r_bloom_colorscale);
7381         Cvar_RegisterVariable(&r_bloom_brighten);
7382         Cvar_RegisterVariable(&r_bloom_blur);
7383         Cvar_RegisterVariable(&r_bloom_resolution);
7384         Cvar_RegisterVariable(&r_bloom_colorexponent);
7385         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7386         Cvar_RegisterVariable(&r_hdr);
7387         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7388         Cvar_RegisterVariable(&r_hdr_glowintensity);
7389         Cvar_RegisterVariable(&r_hdr_range);
7390         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7391         Cvar_RegisterVariable(&developer_texturelogging);
7392         Cvar_RegisterVariable(&gl_lightmaps);
7393         Cvar_RegisterVariable(&r_test);
7394         Cvar_RegisterVariable(&r_glsl_saturation);
7395         Cvar_RegisterVariable(&r_framedatasize);
7396         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7397                 Cvar_SetValue("r_fullbrights", 0);
7398         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7399
7400         Cvar_RegisterVariable(&r_track_sprites);
7401         Cvar_RegisterVariable(&r_track_sprites_flags);
7402         Cvar_RegisterVariable(&r_track_sprites_scalew);
7403         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7404         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7405         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7406 }
7407
7408 extern void R_Textures_Init(void);
7409 extern void GL_Draw_Init(void);
7410 extern void GL_Main_Init(void);
7411 extern void R_Shadow_Init(void);
7412 extern void R_Sky_Init(void);
7413 extern void GL_Surf_Init(void);
7414 extern void R_Particles_Init(void);
7415 extern void R_Explosion_Init(void);
7416 extern void gl_backend_init(void);
7417 extern void Sbar_Init(void);
7418 extern void R_LightningBeams_Init(void);
7419 extern void Mod_RenderInit(void);
7420 extern void Font_Init(void);
7421
7422 void Render_Init(void)
7423 {
7424         gl_backend_init();
7425         R_Textures_Init();
7426         GL_Main_Init();
7427         Font_Init();
7428         GL_Draw_Init();
7429         R_Shadow_Init();
7430         R_Sky_Init();
7431         GL_Surf_Init();
7432         Sbar_Init();
7433         R_Particles_Init();
7434         R_Explosion_Init();
7435         R_LightningBeams_Init();
7436         Mod_RenderInit();
7437 }
7438
7439 /*
7440 ===============
7441 GL_Init
7442 ===============
7443 */
7444 extern char *ENGINE_EXTENSIONS;
7445 void GL_Init (void)
7446 {
7447         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7448         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7449         gl_version = (const char *)qglGetString(GL_VERSION);
7450         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7451
7452         if (!gl_extensions)
7453                 gl_extensions = "";
7454         if (!gl_platformextensions)
7455                 gl_platformextensions = "";
7456
7457         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7458         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7459         Con_Printf("GL_VERSION: %s\n", gl_version);
7460         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7461         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7462
7463         VID_CheckExtensions();
7464
7465         // LordHavoc: report supported extensions
7466         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7467
7468         // clear to black (loading plaque will be seen over this)
7469         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7470 }
7471
7472 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7473 {
7474         int i;
7475         mplane_t *p;
7476         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7477         {
7478                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7479                 if (i == 4)
7480                         continue;
7481                 p = r_refdef.view.frustum + i;
7482                 switch(p->signbits)
7483                 {
7484                 default:
7485                 case 0:
7486                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7487                                 return true;
7488                         break;
7489                 case 1:
7490                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7491                                 return true;
7492                         break;
7493                 case 2:
7494                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7495                                 return true;
7496                         break;
7497                 case 3:
7498                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7499                                 return true;
7500                         break;
7501                 case 4:
7502                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7503                                 return true;
7504                         break;
7505                 case 5:
7506                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7507                                 return true;
7508                         break;
7509                 case 6:
7510                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7511                                 return true;
7512                         break;
7513                 case 7:
7514                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7515                                 return true;
7516                         break;
7517                 }
7518         }
7519         return false;
7520 }
7521
7522 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7523 {
7524         int i;
7525         const mplane_t *p;
7526         for (i = 0;i < numplanes;i++)
7527         {
7528                 p = planes + i;
7529                 switch(p->signbits)
7530                 {
7531                 default:
7532                 case 0:
7533                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7534                                 return true;
7535                         break;
7536                 case 1:
7537                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7538                                 return true;
7539                         break;
7540                 case 2:
7541                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7542                                 return true;
7543                         break;
7544                 case 3:
7545                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 4:
7549                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 case 5:
7553                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7554                                 return true;
7555                         break;
7556                 case 6:
7557                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7558                                 return true;
7559                         break;
7560                 case 7:
7561                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7562                                 return true;
7563                         break;
7564                 }
7565         }
7566         return false;
7567 }
7568
7569 //==================================================================================
7570
7571 // LordHavoc: this stores temporary data used within the same frame
7572
7573 qboolean r_framedata_failed;
7574 static size_t r_framedata_size;
7575 static size_t r_framedata_current;
7576 static void *r_framedata_base;
7577
7578 void R_FrameData_Reset(void)
7579 {
7580         if (r_framedata_base)
7581                 Mem_Free(r_framedata_base);
7582         r_framedata_base = NULL;
7583         r_framedata_size = 0;
7584         r_framedata_current = 0;
7585         r_framedata_failed = false;
7586 }
7587
7588 void R_FrameData_NewFrame(void)
7589 {
7590         size_t wantedsize;
7591         if (r_framedata_failed)
7592                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7593         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7594         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7595         if (r_framedata_size != wantedsize)
7596         {
7597                 r_framedata_size = wantedsize;
7598                 if (r_framedata_base)
7599                         Mem_Free(r_framedata_base);
7600                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7601         }
7602         r_framedata_current = 0;
7603         r_framedata_failed = false;
7604 }
7605
7606 void *R_FrameData_Alloc(size_t size)
7607 {
7608         void *data;
7609
7610         // align to 16 byte boundary
7611         size = (size + 15) & ~15;
7612         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7613         r_framedata_current += size;
7614
7615         // check overflow
7616         if (r_framedata_current > r_framedata_size)
7617                 r_framedata_failed = true;
7618
7619         // return NULL on everything after a failure
7620         if (r_framedata_failed)
7621                 return NULL;
7622
7623         return data;
7624 }
7625
7626 void *R_FrameData_Store(size_t size, void *data)
7627 {
7628         void *d = R_FrameData_Alloc(size);
7629         if (d)
7630                 memcpy(d, data, size);
7631         return d;
7632 }
7633
7634 //==================================================================================
7635
7636 // LordHavoc: animcache originally written by Echon, rewritten since then
7637
7638 /**
7639  * Animation cache prevents re-generating mesh data for an animated model
7640  * multiple times in one frame for lighting, shadowing, reflections, etc.
7641  */
7642
7643 void R_AnimCache_Free(void)
7644 {
7645 }
7646
7647 void R_AnimCache_ClearCache(void)
7648 {
7649         int i;
7650         entity_render_t *ent;
7651
7652         for (i = 0;i < r_refdef.scene.numentities;i++)
7653         {
7654                 ent = r_refdef.scene.entities[i];
7655                 ent->animcache_vertex3f = NULL;
7656                 ent->animcache_normal3f = NULL;
7657                 ent->animcache_svector3f = NULL;
7658                 ent->animcache_tvector3f = NULL;
7659                 ent->animcache_vertexposition = NULL;
7660                 ent->animcache_vertexmesh = NULL;
7661                 ent->animcache_vertexpositionbuffer = NULL;
7662                 ent->animcache_vertexmeshbuffer = NULL;
7663         }
7664 }
7665
7666 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7667 {
7668         int i;
7669         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7670                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7671         if (!ent->animcache_vertexposition)
7672                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7673         if (ent->animcache_vertexposition)
7674         {
7675                 for (i = 0;i < numvertices;i++)
7676                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
7677                 // TODO: upload vertex buffer?
7678         }
7679         if (ent->animcache_vertexmesh)
7680         {
7681                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7682                 for (i = 0;i < numvertices;i++)
7683                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
7684                 if (ent->animcache_svector3f)
7685                         for (i = 0;i < numvertices;i++)
7686                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
7687                 if (ent->animcache_tvector3f)
7688                         for (i = 0;i < numvertices;i++)
7689                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
7690                 if (ent->animcache_normal3f)
7691                         for (i = 0;i < numvertices;i++)
7692                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
7693                 // TODO: upload vertex buffer?
7694         }
7695 }
7696
7697 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7698 {
7699         dp_model_t *model = ent->model;
7700         int numvertices;
7701         // see if it's already cached this frame
7702         if (ent->animcache_vertex3f)
7703         {
7704                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7705                 if (wantnormals || wanttangents)
7706                 {
7707                         if (ent->animcache_normal3f)
7708                                 wantnormals = false;
7709                         if (ent->animcache_svector3f)
7710                                 wanttangents = false;
7711                         if (wantnormals || wanttangents)
7712                         {
7713                                 numvertices = model->surfmesh.num_vertices;
7714                                 if (wantnormals)
7715                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7716                                 if (wanttangents)
7717                                 {
7718                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7719                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7720                                 }
7721                                 if (!r_framedata_failed)
7722                                 {
7723                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7724                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7725                                 }
7726                         }
7727                 }
7728         }
7729         else
7730         {
7731                 // see if this ent is worth caching
7732                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7733                         return false;
7734                 // get some memory for this entity and generate mesh data
7735                 numvertices = model->surfmesh.num_vertices;
7736                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7737                 if (wantnormals)
7738                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7739                 if (wanttangents)
7740                 {
7741                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7742                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7743                 }
7744                 if (!r_framedata_failed)
7745                 {
7746                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7747                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7748                 }
7749         }
7750         return !r_framedata_failed;
7751 }
7752
7753 void R_AnimCache_CacheVisibleEntities(void)
7754 {
7755         int i;
7756         qboolean wantnormals = true;
7757         qboolean wanttangents = !r_showsurfaces.integer;
7758
7759         switch(vid.renderpath)
7760         {
7761         case RENDERPATH_GL20:
7762         case RENDERPATH_CGGL:
7763         case RENDERPATH_D3D9:
7764         case RENDERPATH_D3D10:
7765         case RENDERPATH_D3D11:
7766                 break;
7767         case RENDERPATH_GL13:
7768         case RENDERPATH_GL11:
7769                 wanttangents = false;
7770                 break;
7771         }
7772
7773         if (r_shownormals.integer)
7774                 wanttangents = wantnormals = true;
7775
7776         // TODO: thread this
7777         // NOTE: R_PrepareRTLights() also caches entities
7778
7779         for (i = 0;i < r_refdef.scene.numentities;i++)
7780                 if (r_refdef.viewcache.entityvisible[i])
7781                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7782 }
7783
7784 //==================================================================================
7785
7786 static void R_View_UpdateEntityLighting (void)
7787 {
7788         int i;
7789         entity_render_t *ent;
7790         vec3_t tempdiffusenormal, avg;
7791         vec_t f, fa, fd, fdd;
7792         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7793
7794         for (i = 0;i < r_refdef.scene.numentities;i++)
7795         {
7796                 ent = r_refdef.scene.entities[i];
7797
7798                 // skip unseen models
7799                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7800                         continue;
7801
7802                 // skip bsp models
7803                 if (ent->model && ent->model->brush.num_leafs)
7804                 {
7805                         // TODO: use modellight for r_ambient settings on world?
7806                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7807                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7808                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7809                         continue;
7810                 }
7811
7812                 // fetch the lighting from the worldmodel data
7813                 VectorClear(ent->modellight_ambient);
7814                 VectorClear(ent->modellight_diffuse);
7815                 VectorClear(tempdiffusenormal);
7816                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7817                 {
7818                         vec3_t org;
7819                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7820                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7821                         if(ent->flags & RENDER_EQUALIZE)
7822                         {
7823                                 // first fix up ambient lighting...
7824                                 if(r_equalize_entities_minambient.value > 0)
7825                                 {
7826                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7827                                         if(fd > 0)
7828                                         {
7829                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7830                                                 if(fa < r_equalize_entities_minambient.value * fd)
7831                                                 {
7832                                                         // solve:
7833                                                         //   fa'/fd' = minambient
7834                                                         //   fa'+0.25*fd' = fa+0.25*fd
7835                                                         //   ...
7836                                                         //   fa' = fd' * minambient
7837                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7838                                                         //   ...
7839                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7840                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7841                                                         //   ...
7842                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7843                                                         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
7844                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7845                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7846                                                 }
7847                                         }
7848                                 }
7849
7850                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7851                                 {
7852                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7853                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7854                                         if(f > 0)
7855                                         {
7856                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7857                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7858                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7859                                         }
7860                                 }
7861                         }
7862                 }
7863                 else // highly rare
7864                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7865
7866                 // move the light direction into modelspace coordinates for lighting code
7867                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7868                 if(VectorLength2(ent->modellight_lightdir) == 0)
7869                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7870                 VectorNormalize(ent->modellight_lightdir);
7871         }
7872 }
7873
7874 #define MAX_LINEOFSIGHTTRACES 64
7875
7876 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7877 {
7878         int i;
7879         vec3_t boxmins, boxmaxs;
7880         vec3_t start;
7881         vec3_t end;
7882         dp_model_t *model = r_refdef.scene.worldmodel;
7883
7884         if (!model || !model->brush.TraceLineOfSight)
7885                 return true;
7886
7887         // expand the box a little
7888         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7889         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7890         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7891         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7892         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7893         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7894
7895         // return true if eye is inside enlarged box
7896         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7897                 return true;
7898
7899         // try center
7900         VectorCopy(eye, start);
7901         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7902         if (model->brush.TraceLineOfSight(model, start, end))
7903                 return true;
7904
7905         // try various random positions
7906         for (i = 0;i < numsamples;i++)
7907         {
7908                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7909                 if (model->brush.TraceLineOfSight(model, start, end))
7910                         return true;
7911         }
7912
7913         return false;
7914 }
7915
7916
7917 static void R_View_UpdateEntityVisible (void)
7918 {
7919         int i;
7920         int renderimask;
7921         int samples;
7922         entity_render_t *ent;
7923
7924         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7925                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7926                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7927                 :                                                          RENDER_EXTERIORMODEL;
7928         if (!r_drawviewmodel.integer)
7929                 renderimask |= RENDER_VIEWMODEL;
7930         if (!r_drawexteriormodel.integer)
7931                 renderimask |= RENDER_EXTERIORMODEL;
7932         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7933         {
7934                 // worldmodel can check visibility
7935                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7936                 for (i = 0;i < r_refdef.scene.numentities;i++)
7937                 {
7938                         ent = r_refdef.scene.entities[i];
7939                         if (!(ent->flags & renderimask))
7940                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7941                         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))
7942                                 r_refdef.viewcache.entityvisible[i] = true;
7943                 }
7944                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7945                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7946                 {
7947                         for (i = 0;i < r_refdef.scene.numentities;i++)
7948                         {
7949                                 ent = r_refdef.scene.entities[i];
7950                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7951                                 {
7952                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7953                                         if (samples < 0)
7954                                                 continue; // temp entities do pvs only
7955                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7956                                                 ent->last_trace_visibility = realtime;
7957                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7958                                                 r_refdef.viewcache.entityvisible[i] = 0;
7959                                 }
7960                         }
7961                 }
7962         }
7963         else
7964         {
7965                 // no worldmodel or it can't check visibility
7966                 for (i = 0;i < r_refdef.scene.numentities;i++)
7967                 {
7968                         ent = r_refdef.scene.entities[i];
7969                         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));
7970                 }
7971         }
7972 }
7973
7974 /// only used if skyrendermasked, and normally returns false
7975 int R_DrawBrushModelsSky (void)
7976 {
7977         int i, sky;
7978         entity_render_t *ent;
7979
7980         sky = false;
7981         for (i = 0;i < r_refdef.scene.numentities;i++)
7982         {
7983                 if (!r_refdef.viewcache.entityvisible[i])
7984                         continue;
7985                 ent = r_refdef.scene.entities[i];
7986                 if (!ent->model || !ent->model->DrawSky)
7987                         continue;
7988                 ent->model->DrawSky(ent);
7989                 sky = true;
7990         }
7991         return sky;
7992 }
7993
7994 static void R_DrawNoModel(entity_render_t *ent);
7995 static void R_DrawModels(void)
7996 {
7997         int i;
7998         entity_render_t *ent;
7999
8000         for (i = 0;i < r_refdef.scene.numentities;i++)
8001         {
8002                 if (!r_refdef.viewcache.entityvisible[i])
8003                         continue;
8004                 ent = r_refdef.scene.entities[i];
8005                 r_refdef.stats.entities++;
8006                 if (ent->model && ent->model->Draw != NULL)
8007                         ent->model->Draw(ent);
8008                 else
8009                         R_DrawNoModel(ent);
8010         }
8011 }
8012
8013 static void R_DrawModelsDepth(void)
8014 {
8015         int i;
8016         entity_render_t *ent;
8017
8018         for (i = 0;i < r_refdef.scene.numentities;i++)
8019         {
8020                 if (!r_refdef.viewcache.entityvisible[i])
8021                         continue;
8022                 ent = r_refdef.scene.entities[i];
8023                 if (ent->model && ent->model->DrawDepth != NULL)
8024                         ent->model->DrawDepth(ent);
8025         }
8026 }
8027
8028 static void R_DrawModelsDebug(void)
8029 {
8030         int i;
8031         entity_render_t *ent;
8032
8033         for (i = 0;i < r_refdef.scene.numentities;i++)
8034         {
8035                 if (!r_refdef.viewcache.entityvisible[i])
8036                         continue;
8037                 ent = r_refdef.scene.entities[i];
8038                 if (ent->model && ent->model->DrawDebug != NULL)
8039                         ent->model->DrawDebug(ent);
8040         }
8041 }
8042
8043 static void R_DrawModelsAddWaterPlanes(void)
8044 {
8045         int i;
8046         entity_render_t *ent;
8047
8048         for (i = 0;i < r_refdef.scene.numentities;i++)
8049         {
8050                 if (!r_refdef.viewcache.entityvisible[i])
8051                         continue;
8052                 ent = r_refdef.scene.entities[i];
8053                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8054                         ent->model->DrawAddWaterPlanes(ent);
8055         }
8056 }
8057
8058 static void R_View_SetFrustum(void)
8059 {
8060         int i;
8061         double slopex, slopey;
8062         vec3_t forward, left, up, origin;
8063
8064         // we can't trust r_refdef.view.forward and friends in reflected scenes
8065         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8066
8067 #if 0
8068         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8069         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8070         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8071         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8072         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8073         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8074         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8075         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8076         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8077         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8078         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8079         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8080 #endif
8081
8082 #if 0
8083         zNear = r_refdef.nearclip;
8084         nudge = 1.0 - 1.0 / (1<<23);
8085         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8086         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8087         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8088         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8089         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8090         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8091         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8092         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8093 #endif
8094
8095
8096
8097 #if 0
8098         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8099         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8100         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8101         r_refdef.view.frustum[0].dist = m[15] - m[12];
8102
8103         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8104         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8105         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8106         r_refdef.view.frustum[1].dist = m[15] + m[12];
8107
8108         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8109         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8110         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8111         r_refdef.view.frustum[2].dist = m[15] - m[13];
8112
8113         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8114         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8115         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8116         r_refdef.view.frustum[3].dist = m[15] + m[13];
8117
8118         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8119         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8120         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8121         r_refdef.view.frustum[4].dist = m[15] - m[14];
8122
8123         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8124         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8125         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8126         r_refdef.view.frustum[5].dist = m[15] + m[14];
8127 #endif
8128
8129         if (r_refdef.view.useperspective)
8130         {
8131                 slopex = 1.0 / r_refdef.view.frustum_x;
8132                 slopey = 1.0 / r_refdef.view.frustum_y;
8133                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8134                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8135                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8136                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8137                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8138
8139                 // Leaving those out was a mistake, those were in the old code, and they
8140                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8141                 // I couldn't reproduce it after adding those normalizations. --blub
8142                 VectorNormalize(r_refdef.view.frustum[0].normal);
8143                 VectorNormalize(r_refdef.view.frustum[1].normal);
8144                 VectorNormalize(r_refdef.view.frustum[2].normal);
8145                 VectorNormalize(r_refdef.view.frustum[3].normal);
8146
8147                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8148                 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]);
8149                 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]);
8150                 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]);
8151                 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]);
8152
8153                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8154                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8155                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8156                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8157                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8158         }
8159         else
8160         {
8161                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8162                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8163                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8164                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8165                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8166                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8167                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8168                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8169                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8170                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8171         }
8172         r_refdef.view.numfrustumplanes = 5;
8173
8174         if (r_refdef.view.useclipplane)
8175         {
8176                 r_refdef.view.numfrustumplanes = 6;
8177                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8178         }
8179
8180         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8181                 PlaneClassify(r_refdef.view.frustum + i);
8182
8183         // LordHavoc: note to all quake engine coders, Quake had a special case
8184         // for 90 degrees which assumed a square view (wrong), so I removed it,
8185         // Quake2 has it disabled as well.
8186
8187         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8188         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8189         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8190         //PlaneClassify(&frustum[0]);
8191
8192         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8193         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8194         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8195         //PlaneClassify(&frustum[1]);
8196
8197         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8198         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8199         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8200         //PlaneClassify(&frustum[2]);
8201
8202         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8203         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8204         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8205         //PlaneClassify(&frustum[3]);
8206
8207         // nearclip plane
8208         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8209         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8210         //PlaneClassify(&frustum[4]);
8211 }
8212
8213 void R_View_Update(void)
8214 {
8215         R_Main_ResizeViewCache();
8216         R_View_SetFrustum();
8217         R_View_WorldVisibility(r_refdef.view.useclipplane);
8218         R_View_UpdateEntityVisible();
8219         R_View_UpdateEntityLighting();
8220 }
8221
8222 void R_SetupView(qboolean allowwaterclippingplane)
8223 {
8224         const float *customclipplane = NULL;
8225         float plane[4];
8226         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8227         {
8228                 // LordHavoc: couldn't figure out how to make this approach the
8229                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8230                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8231                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8232                         dist = r_refdef.view.clipplane.dist;
8233                 plane[0] = r_refdef.view.clipplane.normal[0];
8234                 plane[1] = r_refdef.view.clipplane.normal[1];
8235                 plane[2] = r_refdef.view.clipplane.normal[2];
8236                 plane[3] = dist;
8237                 customclipplane = plane;
8238         }
8239
8240         if (!r_refdef.view.useperspective)
8241                 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);
8242         else if (vid.stencil && r_useinfinitefarclip.integer)
8243                 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);
8244         else
8245                 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);
8246         R_SetViewport(&r_refdef.view.viewport);
8247 }
8248
8249 void R_EntityMatrix(const matrix4x4_t *matrix)
8250 {
8251         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8252         {
8253                 gl_modelmatrixchanged = false;
8254                 gl_modelmatrix = *matrix;
8255                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8256                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8257                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8258                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8259                 CHECKGLERROR
8260                 switch(vid.renderpath)
8261                 {
8262                 case RENDERPATH_D3D9:
8263 #ifdef SUPPORTD3D
8264                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8265                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8266 #endif
8267                         break;
8268                 case RENDERPATH_D3D10:
8269                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8270                         break;
8271                 case RENDERPATH_D3D11:
8272                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8273                         break;
8274                 case RENDERPATH_GL20:
8275                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8276                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8277                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8278                         break;
8279                 case RENDERPATH_CGGL:
8280 #ifdef SUPPORTCG
8281                         CHECKCGERROR
8282                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8283                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8284                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8285 #endif
8286                         break;
8287                 case RENDERPATH_GL13:
8288                 case RENDERPATH_GL11:
8289                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8290                         break;
8291                 }
8292         }
8293 }
8294
8295 void R_ResetViewRendering2D(void)
8296 {
8297         r_viewport_t viewport;
8298         DrawQ_Finish();
8299
8300         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8301         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);
8302         R_SetViewport(&viewport);
8303         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8304         GL_Color(1, 1, 1, 1);
8305         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8306         GL_BlendFunc(GL_ONE, GL_ZERO);
8307         GL_AlphaTest(false);
8308         GL_ScissorTest(false);
8309         GL_DepthMask(false);
8310         GL_DepthRange(0, 1);
8311         GL_DepthTest(false);
8312         GL_DepthFunc(GL_LEQUAL);
8313         R_EntityMatrix(&identitymatrix);
8314         R_Mesh_ResetTextureState();
8315         GL_PolygonOffset(0, 0);
8316         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8317         switch(vid.renderpath)
8318         {
8319         case RENDERPATH_GL11:
8320         case RENDERPATH_GL13:
8321         case RENDERPATH_GL20:
8322         case RENDERPATH_CGGL:
8323                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8324                 break;
8325         case RENDERPATH_D3D9:
8326         case RENDERPATH_D3D10:
8327         case RENDERPATH_D3D11:
8328                 break;
8329         }
8330         GL_CullFace(GL_NONE);
8331 }
8332
8333 void R_ResetViewRendering3D(void)
8334 {
8335         DrawQ_Finish();
8336
8337         R_SetupView(true);
8338         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8339         GL_Color(1, 1, 1, 1);
8340         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8341         GL_BlendFunc(GL_ONE, GL_ZERO);
8342         GL_AlphaTest(false);
8343         GL_ScissorTest(true);
8344         GL_DepthMask(true);
8345         GL_DepthRange(0, 1);
8346         GL_DepthTest(true);
8347         GL_DepthFunc(GL_LEQUAL);
8348         R_EntityMatrix(&identitymatrix);
8349         R_Mesh_ResetTextureState();
8350         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8351         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8352         switch(vid.renderpath)
8353         {
8354         case RENDERPATH_GL11:
8355         case RENDERPATH_GL13:
8356         case RENDERPATH_GL20:
8357         case RENDERPATH_CGGL:
8358                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8359                 break;
8360         case RENDERPATH_D3D9:
8361         case RENDERPATH_D3D10:
8362         case RENDERPATH_D3D11:
8363                 break;
8364         }
8365         GL_CullFace(r_refdef.view.cullface_back);
8366 }
8367
8368 /*
8369 ================
8370 R_RenderView_UpdateViewVectors
8371 ================
8372 */
8373 static void R_RenderView_UpdateViewVectors(void)
8374 {
8375         // break apart the view matrix into vectors for various purposes
8376         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8377         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8378         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8379         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8380         // make an inverted copy of the view matrix for tracking sprites
8381         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8382 }
8383
8384 void R_RenderScene(void);
8385 void R_RenderWaterPlanes(void);
8386
8387 static void R_Water_StartFrame(void)
8388 {
8389         int i;
8390         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8391         r_waterstate_waterplane_t *p;
8392
8393         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8394                 return;
8395
8396         switch(vid.renderpath)
8397         {
8398         case RENDERPATH_GL20:
8399         case RENDERPATH_CGGL:
8400         case RENDERPATH_D3D9:
8401         case RENDERPATH_D3D10:
8402         case RENDERPATH_D3D11:
8403                 break;
8404         case RENDERPATH_GL13:
8405         case RENDERPATH_GL11:
8406                 return;
8407         }
8408
8409         // set waterwidth and waterheight to the water resolution that will be
8410         // used (often less than the screen resolution for faster rendering)
8411         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8412         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8413
8414         // calculate desired texture sizes
8415         // can't use water if the card does not support the texture size
8416         if (!r_water.integer || r_showsurfaces.integer)
8417                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8418         else if (vid.support.arb_texture_non_power_of_two)
8419         {
8420                 texturewidth = waterwidth;
8421                 textureheight = waterheight;
8422                 camerawidth = waterwidth;
8423                 cameraheight = waterheight;
8424         }
8425         else
8426         {
8427                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8428                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8429                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8430                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8431         }
8432
8433         // allocate textures as needed
8434         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8435         {
8436                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8437                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8438                 {
8439                         if (p->texture_refraction)
8440                                 R_FreeTexture(p->texture_refraction);
8441                         p->texture_refraction = NULL;
8442                         if (p->texture_reflection)
8443                                 R_FreeTexture(p->texture_reflection);
8444                         p->texture_reflection = NULL;
8445                         if (p->texture_camera)
8446                                 R_FreeTexture(p->texture_camera);
8447                         p->texture_camera = NULL;
8448                 }
8449                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8450                 r_waterstate.texturewidth = texturewidth;
8451                 r_waterstate.textureheight = textureheight;
8452                 r_waterstate.camerawidth = camerawidth;
8453                 r_waterstate.cameraheight = cameraheight;
8454         }
8455
8456         if (r_waterstate.texturewidth)
8457         {
8458                 r_waterstate.enabled = true;
8459
8460                 // when doing a reduced render (HDR) we want to use a smaller area
8461                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8462                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8463
8464                 // set up variables that will be used in shader setup
8465                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8466                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8467                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8468                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8469         }
8470
8471         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8472         r_waterstate.numwaterplanes = 0;
8473 }
8474
8475 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8476 {
8477         int triangleindex, planeindex;
8478         const int *e;
8479         vec3_t vert[3];
8480         vec3_t normal;
8481         vec3_t center;
8482         mplane_t plane;
8483         int cam_ent;
8484         r_waterstate_waterplane_t *p;
8485         texture_t *t = R_GetCurrentTexture(surface->texture);
8486         cam_ent = t->camera_entity;
8487         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8488                 cam_ent = 0;
8489
8490         // just use the first triangle with a valid normal for any decisions
8491         VectorClear(normal);
8492         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8493         {
8494                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8495                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8496                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8497                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8498                 if (VectorLength2(normal) >= 0.001)
8499                         break;
8500         }
8501
8502         VectorCopy(normal, plane.normal);
8503         VectorNormalize(plane.normal);
8504         plane.dist = DotProduct(vert[0], plane.normal);
8505         PlaneClassify(&plane);
8506         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8507         {
8508                 // skip backfaces (except if nocullface is set)
8509                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8510                         return;
8511                 VectorNegate(plane.normal, plane.normal);
8512                 plane.dist *= -1;
8513                 PlaneClassify(&plane);
8514         }
8515
8516
8517         // find a matching plane if there is one
8518         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8519                 if(p->camera_entity == t->camera_entity)
8520                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8521                                 break;
8522         if (planeindex >= r_waterstate.maxwaterplanes)
8523                 return; // nothing we can do, out of planes
8524
8525         // if this triangle does not fit any known plane rendered this frame, add one
8526         if (planeindex >= r_waterstate.numwaterplanes)
8527         {
8528                 // store the new plane
8529                 r_waterstate.numwaterplanes++;
8530                 p->plane = plane;
8531                 // clear materialflags and pvs
8532                 p->materialflags = 0;
8533                 p->pvsvalid = false;
8534                 p->camera_entity = t->camera_entity;
8535         }
8536         // merge this surface's materialflags into the waterplane
8537         p->materialflags |= t->currentmaterialflags;
8538         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8539         {
8540                 // merge this surface's PVS into the waterplane
8541                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8542                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8543                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8544                 {
8545                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8546                         p->pvsvalid = true;
8547                 }
8548         }
8549 }
8550
8551 static void R_Water_ProcessPlanes(void)
8552 {
8553         r_refdef_view_t originalview;
8554         r_refdef_view_t myview;
8555         int planeindex;
8556         r_waterstate_waterplane_t *p;
8557         vec3_t visorigin;
8558
8559         originalview = r_refdef.view;
8560
8561         // make sure enough textures are allocated
8562         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8563         {
8564                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8565                 {
8566                         if (!p->texture_refraction)
8567                                 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);
8568                         if (!p->texture_refraction)
8569                                 goto error;
8570                 }
8571                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8572                 {
8573                         if (!p->texture_camera)
8574                                 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);
8575                         if (!p->texture_camera)
8576                                 goto error;
8577                 }
8578
8579                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8580                 {
8581                         if (!p->texture_reflection)
8582                                 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);
8583                         if (!p->texture_reflection)
8584                                 goto error;
8585                 }
8586         }
8587
8588         // render views
8589         r_refdef.view = originalview;
8590         r_refdef.view.showdebug = false;
8591         r_refdef.view.width = r_waterstate.waterwidth;
8592         r_refdef.view.height = r_waterstate.waterheight;
8593         r_refdef.view.useclipplane = true;
8594         myview = r_refdef.view;
8595         r_waterstate.renderingscene = true;
8596         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8597         {
8598                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8599                 {
8600                         r_refdef.view = myview;
8601                         // render reflected scene and copy into texture
8602                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8603                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8604                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8605                         r_refdef.view.clipplane = p->plane;
8606                         // reverse the cullface settings for this render
8607                         r_refdef.view.cullface_front = GL_FRONT;
8608                         r_refdef.view.cullface_back = GL_BACK;
8609                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8610                         {
8611                                 r_refdef.view.usecustompvs = true;
8612                                 if (p->pvsvalid)
8613                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8614                                 else
8615                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8616                         }
8617
8618                         R_ResetViewRendering3D();
8619                         R_ClearScreen(r_refdef.fogenabled);
8620                         R_View_Update();
8621                         R_RenderScene();
8622
8623                         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);
8624                 }
8625
8626                 // render the normal view scene and copy into texture
8627                 // (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)
8628                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8629                 {
8630                         r_waterstate.renderingrefraction = true;
8631                         r_refdef.view = myview;
8632
8633                         r_refdef.view.clipplane = p->plane;
8634                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8635                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8636
8637                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8638                         {
8639                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8640                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8641                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8642                                 R_RenderView_UpdateViewVectors();
8643                                 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);
8644                         }
8645
8646                         PlaneClassify(&r_refdef.view.clipplane);
8647
8648                         R_ResetViewRendering3D();
8649                         R_ClearScreen(r_refdef.fogenabled);
8650                         R_View_Update();
8651                         R_RenderScene();
8652
8653                         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);
8654                         r_waterstate.renderingrefraction = false;
8655                 }
8656                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8657                 {
8658                         r_refdef.view = myview;
8659
8660                         r_refdef.view.clipplane = p->plane;
8661                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8662                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8663
8664                         r_refdef.view.width = r_waterstate.camerawidth;
8665                         r_refdef.view.height = r_waterstate.cameraheight;
8666                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8667                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8668
8669                         if(p->camera_entity)
8670                         {
8671                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8672                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8673                         }
8674
8675                         // reverse the cullface settings for this render
8676                         r_refdef.view.cullface_front = GL_FRONT;
8677                         r_refdef.view.cullface_back = GL_BACK;
8678                         // also reverse the view matrix
8679                         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
8680                         R_RenderView_UpdateViewVectors();
8681                         if(p->camera_entity)
8682                                 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);
8683                         
8684                         // camera needs no clipplane
8685                         r_refdef.view.useclipplane = false;
8686
8687                         PlaneClassify(&r_refdef.view.clipplane);
8688
8689                         R_ResetViewRendering3D();
8690                         R_ClearScreen(r_refdef.fogenabled);
8691                         R_View_Update();
8692                         R_RenderScene();
8693
8694                         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);
8695                         r_waterstate.renderingrefraction = false;
8696                 }
8697
8698         }
8699         r_waterstate.renderingscene = false;
8700         r_refdef.view = originalview;
8701         R_ResetViewRendering3D();
8702         R_ClearScreen(r_refdef.fogenabled);
8703         R_View_Update();
8704         return;
8705 error:
8706         r_refdef.view = originalview;
8707         r_waterstate.renderingscene = false;
8708         Cvar_SetValueQuick(&r_water, 0);
8709         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8710         return;
8711 }
8712
8713 void R_Bloom_StartFrame(void)
8714 {
8715         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8716
8717         switch(vid.renderpath)
8718         {
8719         case RENDERPATH_GL20:
8720         case RENDERPATH_CGGL:
8721         case RENDERPATH_D3D9:
8722         case RENDERPATH_D3D10:
8723         case RENDERPATH_D3D11:
8724                 break;
8725         case RENDERPATH_GL13:
8726         case RENDERPATH_GL11:
8727                 return;
8728         }
8729
8730         // set bloomwidth and bloomheight to the bloom resolution that will be
8731         // used (often less than the screen resolution for faster rendering)
8732         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8733         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8734         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8735         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8736         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8737
8738         // calculate desired texture sizes
8739         if (vid.support.arb_texture_non_power_of_two)
8740         {
8741                 screentexturewidth = r_refdef.view.width;
8742                 screentextureheight = r_refdef.view.height;
8743                 bloomtexturewidth = r_bloomstate.bloomwidth;
8744                 bloomtextureheight = r_bloomstate.bloomheight;
8745         }
8746         else
8747         {
8748                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8749                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8750                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8751                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8752         }
8753
8754         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))
8755         {
8756                 Cvar_SetValueQuick(&r_hdr, 0);
8757                 Cvar_SetValueQuick(&r_bloom, 0);
8758                 Cvar_SetValueQuick(&r_motionblur, 0);
8759                 Cvar_SetValueQuick(&r_damageblur, 0);
8760         }
8761
8762         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)))
8763                 screentexturewidth = screentextureheight = 0;
8764         if (!r_hdr.integer && !r_bloom.integer)
8765                 bloomtexturewidth = bloomtextureheight = 0;
8766
8767         // allocate textures as needed
8768         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8769         {
8770                 if (r_bloomstate.texture_screen)
8771                         R_FreeTexture(r_bloomstate.texture_screen);
8772                 r_bloomstate.texture_screen = NULL;
8773                 r_bloomstate.screentexturewidth = screentexturewidth;
8774                 r_bloomstate.screentextureheight = screentextureheight;
8775                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8776                         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);
8777         }
8778         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8779         {
8780                 if (r_bloomstate.texture_bloom)
8781                         R_FreeTexture(r_bloomstate.texture_bloom);
8782                 r_bloomstate.texture_bloom = NULL;
8783                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8784                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8785                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8786                         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);
8787         }
8788
8789         // when doing a reduced render (HDR) we want to use a smaller area
8790         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8791         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8792         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8793         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8794         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8795
8796         // set up a texcoord array for the full resolution screen image
8797         // (we have to keep this around to copy back during final render)
8798         r_bloomstate.screentexcoord2f[0] = 0;
8799         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8800         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8801         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8802         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8803         r_bloomstate.screentexcoord2f[5] = 0;
8804         r_bloomstate.screentexcoord2f[6] = 0;
8805         r_bloomstate.screentexcoord2f[7] = 0;
8806
8807         // set up a texcoord array for the reduced resolution bloom image
8808         // (which will be additive blended over the screen image)
8809         r_bloomstate.bloomtexcoord2f[0] = 0;
8810         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8811         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8812         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8813         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8814         r_bloomstate.bloomtexcoord2f[5] = 0;
8815         r_bloomstate.bloomtexcoord2f[6] = 0;
8816         r_bloomstate.bloomtexcoord2f[7] = 0;
8817
8818         switch(vid.renderpath)
8819         {
8820         case RENDERPATH_D3D9:
8821         case RENDERPATH_D3D10:
8822         case RENDERPATH_D3D11:
8823                 {
8824                         int i;
8825                         for (i = 0;i < 4;i++)
8826                         {
8827                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8828                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8829                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8830                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8831                         }
8832                 }
8833                 break;
8834         }
8835
8836         if (r_hdr.integer || r_bloom.integer)
8837         {
8838                 r_bloomstate.enabled = true;
8839                 r_bloomstate.hdr = r_hdr.integer != 0;
8840         }
8841
8842         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);
8843 }
8844
8845 void R_Bloom_CopyBloomTexture(float colorscale)
8846 {
8847         r_refdef.stats.bloom++;
8848
8849         // scale down screen texture to the bloom texture size
8850         CHECKGLERROR
8851         R_SetViewport(&r_bloomstate.viewport);
8852         GL_BlendFunc(GL_ONE, GL_ZERO);
8853         GL_Color(colorscale, colorscale, colorscale, 1);
8854         // 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...
8855         switch(vid.renderpath)
8856         {
8857         case RENDERPATH_GL11:
8858         case RENDERPATH_GL13:
8859         case RENDERPATH_GL20:
8860         case RENDERPATH_CGGL:
8861                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8862                 break;
8863         case RENDERPATH_D3D9:
8864         case RENDERPATH_D3D10:
8865         case RENDERPATH_D3D11:
8866                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8867                 break;
8868         }
8869         // TODO: do boxfilter scale-down in shader?
8870         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8871         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8872         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8873
8874         // we now have a bloom image in the framebuffer
8875         // copy it into the bloom image texture for later processing
8876         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8877         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8878 }
8879
8880 void R_Bloom_CopyHDRTexture(void)
8881 {
8882         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);
8883         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8884 }
8885
8886 void R_Bloom_MakeTexture(void)
8887 {
8888         int x, range, dir;
8889         float xoffset, yoffset, r, brighten;
8890
8891         r_refdef.stats.bloom++;
8892
8893         R_ResetViewRendering2D();
8894
8895         // we have a bloom image in the framebuffer
8896         CHECKGLERROR
8897         R_SetViewport(&r_bloomstate.viewport);
8898
8899         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8900         {
8901                 x *= 2;
8902                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8903                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8904                 GL_Color(r,r,r,1);
8905                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8906                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8907                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8908                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8909
8910                 // copy the vertically blurred bloom view to a texture
8911                 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);
8912                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8913         }
8914
8915         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8916         brighten = r_bloom_brighten.value;
8917         if (r_hdr.integer)
8918                 brighten *= r_hdr_range.value;
8919         brighten = sqrt(brighten);
8920         if(range >= 1)
8921                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8922         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8923
8924         for (dir = 0;dir < 2;dir++)
8925         {
8926                 // blend on at multiple vertical offsets to achieve a vertical blur
8927                 // TODO: do offset blends using GLSL
8928                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8929                 GL_BlendFunc(GL_ONE, GL_ZERO);
8930                 for (x = -range;x <= range;x++)
8931                 {
8932                         if (!dir){xoffset = 0;yoffset = x;}
8933                         else {xoffset = x;yoffset = 0;}
8934                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8935                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8936                         // compute a texcoord array with the specified x and y offset
8937                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8938                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8939                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8940                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8941                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8942                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8943                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8944                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8945                         // this r value looks like a 'dot' particle, fading sharply to
8946                         // black at the edges
8947                         // (probably not realistic but looks good enough)
8948                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8949                         //r = brighten/(range*2+1);
8950                         r = brighten / (range * 2 + 1);
8951                         if(range >= 1)
8952                                 r *= (1 - x*x/(float)(range*range));
8953                         GL_Color(r, r, r, 1);
8954                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8955                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8956                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8957                         GL_BlendFunc(GL_ONE, GL_ONE);
8958                 }
8959
8960                 // copy the vertically blurred bloom view to a texture
8961                 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);
8962                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8963         }
8964 }
8965
8966 void R_HDR_RenderBloomTexture(void)
8967 {
8968         int oldwidth, oldheight;
8969         float oldcolorscale;
8970
8971         oldcolorscale = r_refdef.view.colorscale;
8972         oldwidth = r_refdef.view.width;
8973         oldheight = r_refdef.view.height;
8974         r_refdef.view.width = r_bloomstate.bloomwidth;
8975         r_refdef.view.height = r_bloomstate.bloomheight;
8976
8977         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8978         // TODO: add exposure compensation features
8979         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8980
8981         r_refdef.view.showdebug = false;
8982         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8983
8984         R_ResetViewRendering3D();
8985
8986         R_ClearScreen(r_refdef.fogenabled);
8987         if (r_timereport_active)
8988                 R_TimeReport("HDRclear");
8989
8990         R_View_Update();
8991         if (r_timereport_active)
8992                 R_TimeReport("visibility");
8993
8994         // only do secondary renders with HDR if r_hdr is 2 or higher
8995         r_waterstate.numwaterplanes = 0;
8996         if (r_waterstate.enabled && r_hdr.integer >= 2)
8997                 R_RenderWaterPlanes();
8998
8999         r_refdef.view.showdebug = true;
9000         R_RenderScene();
9001         r_waterstate.numwaterplanes = 0;
9002
9003         R_ResetViewRendering2D();
9004
9005         R_Bloom_CopyHDRTexture();
9006         R_Bloom_MakeTexture();
9007
9008         // restore the view settings
9009         r_refdef.view.width = oldwidth;
9010         r_refdef.view.height = oldheight;
9011         r_refdef.view.colorscale = oldcolorscale;
9012
9013         R_ResetViewRendering3D();
9014
9015         R_ClearScreen(r_refdef.fogenabled);
9016         if (r_timereport_active)
9017                 R_TimeReport("viewclear");
9018 }
9019
9020 static void R_BlendView(void)
9021 {
9022         unsigned int permutation;
9023         float uservecs[4][4];
9024
9025         switch (vid.renderpath)
9026         {
9027         case RENDERPATH_GL20:
9028         case RENDERPATH_CGGL:
9029         case RENDERPATH_D3D9:
9030         case RENDERPATH_D3D10:
9031         case RENDERPATH_D3D11:
9032                 permutation =
9033                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9034                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9035                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9036                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9037                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9038
9039                 if (r_bloomstate.texture_screen)
9040                 {
9041                         // make sure the buffer is available
9042                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9043
9044                         R_ResetViewRendering2D();
9045
9046                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9047                         {
9048                                 // declare variables
9049                                 float speed;
9050                                 static float avgspeed;
9051
9052                                 speed = VectorLength(cl.movement_velocity);
9053
9054                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9055                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9056
9057                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9058                                 speed = bound(0, speed, 1);
9059                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9060
9061                                 // calculate values into a standard alpha
9062                                 cl.motionbluralpha = 1 - exp(-
9063                                                 (
9064                                                  (r_motionblur.value * speed / 80)
9065                                                  +
9066                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9067                                                 )
9068                                                 /
9069                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9070                                            );
9071
9072                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9073                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9074                                 // apply the blur
9075                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9076                                 {
9077                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9078                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9079                                         switch(vid.renderpath)
9080                                         {
9081                                         case RENDERPATH_GL11:
9082                                         case RENDERPATH_GL13:
9083                                         case RENDERPATH_GL20:
9084                                         case RENDERPATH_CGGL:
9085                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9086                                                 break;
9087                                         case RENDERPATH_D3D9:
9088                                         case RENDERPATH_D3D10:
9089                                         case RENDERPATH_D3D11:
9090                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9091                                                 break;
9092                                         }
9093                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9094                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9095                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9096                                 }
9097                         }
9098
9099                         // copy view into the screen texture
9100                         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);
9101                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9102                 }
9103                 else if (!r_bloomstate.texture_bloom)
9104                 {
9105                         // we may still have to do view tint...
9106                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9107                         {
9108                                 // apply a color tint to the whole view
9109                                 R_ResetViewRendering2D();
9110                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9111                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9112                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9113                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9114                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9115                         }
9116                         break; // no screen processing, no bloom, skip it
9117                 }
9118
9119                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9120                 {
9121                         // render simple bloom effect
9122                         // copy the screen and shrink it and darken it for the bloom process
9123                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9124                         // make the bloom texture
9125                         R_Bloom_MakeTexture();
9126                 }
9127
9128 #if _MSC_VER >= 1400
9129 #define sscanf sscanf_s
9130 #endif
9131                 memset(uservecs, 0, sizeof(uservecs));
9132                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9133                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9134                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9135                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9136
9137                 R_ResetViewRendering2D();
9138                 GL_Color(1, 1, 1, 1);
9139                 GL_BlendFunc(GL_ONE, GL_ZERO);
9140
9141                 switch(vid.renderpath)
9142                 {
9143                 case RENDERPATH_GL20:
9144                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9145                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9146                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9147                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9148                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9149                         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]);
9150                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9151                         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]);
9152                         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]);
9153                         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]);
9154                         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]);
9155                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9156                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9157                         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);
9158                         break;
9159                 case RENDERPATH_CGGL:
9160 #ifdef SUPPORTCG
9161                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9162                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9163                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9164                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9165                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9166                         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
9167                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9168                         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
9169                         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
9170                         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
9171                         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
9172                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9173                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9174                         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);
9175 #endif
9176                         break;
9177                 case RENDERPATH_D3D9:
9178 #ifdef SUPPORTD3D
9179                         // 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...
9180                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9181                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9182                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9183                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9184                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9185                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9186                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9187                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9188                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9189                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9190                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9191                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9192                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9193                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9194 #endif
9195                         break;
9196                 case RENDERPATH_D3D10:
9197                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9198                         break;
9199                 case RENDERPATH_D3D11:
9200                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9201                         break;
9202                 default:
9203                         break;
9204                 }
9205                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9206                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9207                 break;
9208         case RENDERPATH_GL13:
9209         case RENDERPATH_GL11:
9210                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9211                 {
9212                         // apply a color tint to the whole view
9213                         R_ResetViewRendering2D();
9214                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9215                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9216                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9217                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9218                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9219                 }
9220                 break;
9221         }
9222 }
9223
9224 matrix4x4_t r_waterscrollmatrix;
9225
9226 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9227 {
9228         if (r_refdef.fog_density)
9229         {
9230                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9231                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9232                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9233
9234                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9235                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9236                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9237                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9238
9239                 {
9240                         vec3_t fogvec;
9241                         VectorCopy(r_refdef.fogcolor, fogvec);
9242                         //   color.rgb *= ContrastBoost * SceneBrightness;
9243                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9244                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9245                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9246                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9247                 }
9248         }
9249 }
9250
9251 void R_UpdateVariables(void)
9252 {
9253         R_Textures_Frame();
9254
9255         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9256
9257         r_refdef.farclip = r_farclip_base.value;
9258         if (r_refdef.scene.worldmodel)
9259                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9260         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9261
9262         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9263                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9264         r_refdef.polygonfactor = 0;
9265         r_refdef.polygonoffset = 0;
9266         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9267         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9268
9269         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9270         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9271         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9272         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9273         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9274         if (r_showsurfaces.integer)
9275         {
9276                 r_refdef.scene.rtworld = false;
9277                 r_refdef.scene.rtworldshadows = false;
9278                 r_refdef.scene.rtdlight = false;
9279                 r_refdef.scene.rtdlightshadows = false;
9280                 r_refdef.lightmapintensity = 0;
9281         }
9282
9283         if (gamemode == GAME_NEHAHRA)
9284         {
9285                 if (gl_fogenable.integer)
9286                 {
9287                         r_refdef.oldgl_fogenable = true;
9288                         r_refdef.fog_density = gl_fogdensity.value;
9289                         r_refdef.fog_red = gl_fogred.value;
9290                         r_refdef.fog_green = gl_foggreen.value;
9291                         r_refdef.fog_blue = gl_fogblue.value;
9292                         r_refdef.fog_alpha = 1;
9293                         r_refdef.fog_start = 0;
9294                         r_refdef.fog_end = gl_skyclip.value;
9295                         r_refdef.fog_height = 1<<30;
9296                         r_refdef.fog_fadedepth = 128;
9297                 }
9298                 else if (r_refdef.oldgl_fogenable)
9299                 {
9300                         r_refdef.oldgl_fogenable = false;
9301                         r_refdef.fog_density = 0;
9302                         r_refdef.fog_red = 0;
9303                         r_refdef.fog_green = 0;
9304                         r_refdef.fog_blue = 0;
9305                         r_refdef.fog_alpha = 0;
9306                         r_refdef.fog_start = 0;
9307                         r_refdef.fog_end = 0;
9308                         r_refdef.fog_height = 1<<30;
9309                         r_refdef.fog_fadedepth = 128;
9310                 }
9311         }
9312
9313         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9314         r_refdef.fog_start = max(0, r_refdef.fog_start);
9315         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9316
9317         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9318
9319         if (r_refdef.fog_density && r_drawfog.integer)
9320         {
9321                 r_refdef.fogenabled = true;
9322                 // this is the point where the fog reaches 0.9986 alpha, which we
9323                 // consider a good enough cutoff point for the texture
9324                 // (0.9986 * 256 == 255.6)
9325                 if (r_fog_exp2.integer)
9326                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9327                 else
9328                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9329                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9330                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9331                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9332                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9333                         R_BuildFogHeightTexture();
9334                 // fog color was already set
9335                 // update the fog texture
9336                 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)
9337                         R_BuildFogTexture();
9338                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9339                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9340         }
9341         else
9342                 r_refdef.fogenabled = false;
9343
9344         switch(vid.renderpath)
9345         {
9346         case RENDERPATH_GL20:
9347         case RENDERPATH_CGGL:
9348         case RENDERPATH_D3D9:
9349         case RENDERPATH_D3D10:
9350         case RENDERPATH_D3D11:
9351                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9352                 {
9353                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9354                         {
9355                                 // build GLSL gamma texture
9356 #define RAMPWIDTH 256
9357                                 unsigned short ramp[RAMPWIDTH * 3];
9358                                 unsigned char rampbgr[RAMPWIDTH][4];
9359                                 int i;
9360
9361                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9362
9363                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9364                                 for(i = 0; i < RAMPWIDTH; ++i)
9365                                 {
9366                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9367                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9368                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9369                                         rampbgr[i][3] = 0;
9370                                 }
9371                                 if (r_texture_gammaramps)
9372                                 {
9373                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9374                                 }
9375                                 else
9376                                 {
9377                                         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);
9378                                 }
9379                         }
9380                 }
9381                 else
9382                 {
9383                         // remove GLSL gamma texture
9384                 }
9385                 break;
9386         case RENDERPATH_GL13:
9387         case RENDERPATH_GL11:
9388                 break;
9389         }
9390 }
9391
9392 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9393 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9394 /*
9395 ================
9396 R_SelectScene
9397 ================
9398 */
9399 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9400         if( scenetype != r_currentscenetype ) {
9401                 // store the old scenetype
9402                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9403                 r_currentscenetype = scenetype;
9404                 // move in the new scene
9405                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9406         }
9407 }
9408
9409 /*
9410 ================
9411 R_GetScenePointer
9412 ================
9413 */
9414 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9415 {
9416         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9417         if( scenetype == r_currentscenetype ) {
9418                 return &r_refdef.scene;
9419         } else {
9420                 return &r_scenes_store[ scenetype ];
9421         }
9422 }
9423
9424 /*
9425 ================
9426 R_RenderView
9427 ================
9428 */
9429 void R_RenderView(void)
9430 {
9431         if (r_timereport_active)
9432                 R_TimeReport("start");
9433         r_textureframe++; // used only by R_GetCurrentTexture
9434         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9435
9436         if (!r_drawentities.integer)
9437                 r_refdef.scene.numentities = 0;
9438
9439         R_AnimCache_ClearCache();
9440         R_FrameData_NewFrame();
9441
9442         if (r_refdef.view.isoverlay)
9443         {
9444                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9445                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9446                 R_TimeReport("depthclear");
9447
9448                 r_refdef.view.showdebug = false;
9449
9450                 r_waterstate.enabled = false;
9451                 r_waterstate.numwaterplanes = 0;
9452
9453                 R_RenderScene();
9454
9455                 CHECKGLERROR
9456                 return;
9457         }
9458
9459         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9460                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9461
9462         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9463
9464         R_RenderView_UpdateViewVectors();
9465
9466         R_Shadow_UpdateWorldLightSelection();
9467
9468         R_Bloom_StartFrame();
9469         R_Water_StartFrame();
9470
9471         CHECKGLERROR
9472         if (r_timereport_active)
9473                 R_TimeReport("viewsetup");
9474
9475         R_ResetViewRendering3D();
9476
9477         if (r_refdef.view.clear || r_refdef.fogenabled)
9478         {
9479                 R_ClearScreen(r_refdef.fogenabled);
9480                 if (r_timereport_active)
9481                         R_TimeReport("viewclear");
9482         }
9483         r_refdef.view.clear = true;
9484
9485         // this produces a bloom texture to be used in R_BlendView() later
9486         if (r_hdr.integer && r_bloomstate.bloomwidth)
9487         {
9488                 R_HDR_RenderBloomTexture();
9489                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9490                 r_textureframe++; // used only by R_GetCurrentTexture
9491         }
9492
9493         r_refdef.view.showdebug = true;
9494
9495         R_View_Update();
9496         if (r_timereport_active)
9497                 R_TimeReport("visibility");
9498
9499         r_waterstate.numwaterplanes = 0;
9500         if (r_waterstate.enabled)
9501                 R_RenderWaterPlanes();
9502
9503         R_RenderScene();
9504         r_waterstate.numwaterplanes = 0;
9505
9506         R_BlendView();
9507         if (r_timereport_active)
9508                 R_TimeReport("blendview");
9509
9510         GL_Scissor(0, 0, vid.width, vid.height);
9511         GL_ScissorTest(false);
9512         CHECKGLERROR
9513 }
9514
9515 void R_RenderWaterPlanes(void)
9516 {
9517         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9518         {
9519                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9520                 if (r_timereport_active)
9521                         R_TimeReport("waterworld");
9522         }
9523
9524         // don't let sound skip if going slow
9525         if (r_refdef.scene.extraupdate)
9526                 S_ExtraUpdate ();
9527
9528         R_DrawModelsAddWaterPlanes();
9529         if (r_timereport_active)
9530                 R_TimeReport("watermodels");
9531
9532         if (r_waterstate.numwaterplanes)
9533         {
9534                 R_Water_ProcessPlanes();
9535                 if (r_timereport_active)
9536                         R_TimeReport("waterscenes");
9537         }
9538 }
9539
9540 extern void R_DrawLightningBeams (void);
9541 extern void VM_CL_AddPolygonsToMeshQueue (void);
9542 extern void R_DrawPortals (void);
9543 extern cvar_t cl_locs_show;
9544 static void R_DrawLocs(void);
9545 static void R_DrawEntityBBoxes(void);
9546 static void R_DrawModelDecals(void);
9547 extern void R_DrawModelShadows(void);
9548 extern void R_DrawModelShadowMaps(void);
9549 extern cvar_t cl_decals_newsystem;
9550 extern qboolean r_shadow_usingdeferredprepass;
9551 void R_RenderScene(void)
9552 {
9553         qboolean shadowmapping = false;
9554
9555         if (r_timereport_active)
9556                 R_TimeReport("beginscene");
9557
9558         r_refdef.stats.renders++;
9559
9560         R_UpdateFogColor();
9561
9562         // don't let sound skip if going slow
9563         if (r_refdef.scene.extraupdate)
9564                 S_ExtraUpdate ();
9565
9566         R_MeshQueue_BeginScene();
9567
9568         R_SkyStartFrame();
9569
9570         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);
9571
9572         if (r_timereport_active)
9573                 R_TimeReport("skystartframe");
9574
9575         if (cl.csqc_vidvars.drawworld)
9576         {
9577                 // don't let sound skip if going slow
9578                 if (r_refdef.scene.extraupdate)
9579                         S_ExtraUpdate ();
9580
9581                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9582                 {
9583                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9584                         if (r_timereport_active)
9585                                 R_TimeReport("worldsky");
9586                 }
9587
9588                 if (R_DrawBrushModelsSky() && r_timereport_active)
9589                         R_TimeReport("bmodelsky");
9590
9591                 if (skyrendermasked && skyrenderlater)
9592                 {
9593                         // we have to force off the water clipping plane while rendering sky
9594                         R_SetupView(false);
9595                         R_Sky();
9596                         R_SetupView(true);
9597                         if (r_timereport_active)
9598                                 R_TimeReport("sky");
9599                 }
9600         }
9601
9602         R_AnimCache_CacheVisibleEntities();
9603         if (r_timereport_active)
9604                 R_TimeReport("animation");
9605
9606         R_Shadow_PrepareLights();
9607         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9608                 R_Shadow_PrepareModelShadows();
9609         if (r_timereport_active)
9610                 R_TimeReport("preparelights");
9611
9612         if (R_Shadow_ShadowMappingEnabled())
9613                 shadowmapping = true;
9614
9615         if (r_shadow_usingdeferredprepass)
9616                 R_Shadow_DrawPrepass();
9617
9618         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9619         {
9620                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9621                 if (r_timereport_active)
9622                         R_TimeReport("worlddepth");
9623         }
9624         if (r_depthfirst.integer >= 2)
9625         {
9626                 R_DrawModelsDepth();
9627                 if (r_timereport_active)
9628                         R_TimeReport("modeldepth");
9629         }
9630
9631         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9632         {
9633                 R_DrawModelShadowMaps();
9634                 R_ResetViewRendering3D();
9635                 // don't let sound skip if going slow
9636                 if (r_refdef.scene.extraupdate)
9637                         S_ExtraUpdate ();
9638         }
9639
9640         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9641         {
9642                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9643                 if (r_timereport_active)
9644                         R_TimeReport("world");
9645         }
9646
9647         // don't let sound skip if going slow
9648         if (r_refdef.scene.extraupdate)
9649                 S_ExtraUpdate ();
9650
9651         R_DrawModels();
9652         if (r_timereport_active)
9653                 R_TimeReport("models");
9654
9655         // don't let sound skip if going slow
9656         if (r_refdef.scene.extraupdate)
9657                 S_ExtraUpdate ();
9658
9659         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9660         {
9661                 R_DrawModelShadows();
9662                 R_ResetViewRendering3D();
9663                 // don't let sound skip if going slow
9664                 if (r_refdef.scene.extraupdate)
9665                         S_ExtraUpdate ();
9666         }
9667
9668         if (!r_shadow_usingdeferredprepass)
9669         {
9670                 R_Shadow_DrawLights();
9671                 if (r_timereport_active)
9672                         R_TimeReport("rtlights");
9673         }
9674
9675         // don't let sound skip if going slow
9676         if (r_refdef.scene.extraupdate)
9677                 S_ExtraUpdate ();
9678
9679         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9680         {
9681                 R_DrawModelShadows();
9682                 R_ResetViewRendering3D();
9683                 // don't let sound skip if going slow
9684                 if (r_refdef.scene.extraupdate)
9685                         S_ExtraUpdate ();
9686         }
9687
9688         if (cl.csqc_vidvars.drawworld)
9689         {
9690                 if (cl_decals_newsystem.integer)
9691                 {
9692                         R_DrawModelDecals();
9693                         if (r_timereport_active)
9694                                 R_TimeReport("modeldecals");
9695                 }
9696                 else
9697                 {
9698                         R_DrawDecals();
9699                         if (r_timereport_active)
9700                                 R_TimeReport("decals");
9701                 }
9702
9703                 R_DrawParticles();
9704                 if (r_timereport_active)
9705                         R_TimeReport("particles");
9706
9707                 R_DrawExplosions();
9708                 if (r_timereport_active)
9709                         R_TimeReport("explosions");
9710
9711                 R_DrawLightningBeams();
9712                 if (r_timereport_active)
9713                         R_TimeReport("lightning");
9714         }
9715
9716         VM_CL_AddPolygonsToMeshQueue();
9717
9718         if (r_refdef.view.showdebug)
9719         {
9720                 if (cl_locs_show.integer)
9721                 {
9722                         R_DrawLocs();
9723                         if (r_timereport_active)
9724                                 R_TimeReport("showlocs");
9725                 }
9726
9727                 if (r_drawportals.integer)
9728                 {
9729                         R_DrawPortals();
9730                         if (r_timereport_active)
9731                                 R_TimeReport("portals");
9732                 }
9733
9734                 if (r_showbboxes.value > 0)
9735                 {
9736                         R_DrawEntityBBoxes();
9737                         if (r_timereport_active)
9738                                 R_TimeReport("bboxes");
9739                 }
9740         }
9741
9742         R_MeshQueue_RenderTransparent();
9743         if (r_timereport_active)
9744                 R_TimeReport("drawtrans");
9745
9746         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))
9747         {
9748                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9749                 if (r_timereport_active)
9750                         R_TimeReport("worlddebug");
9751                 R_DrawModelsDebug();
9752                 if (r_timereport_active)
9753                         R_TimeReport("modeldebug");
9754         }
9755
9756         if (cl.csqc_vidvars.drawworld)
9757         {
9758                 R_Shadow_DrawCoronas();
9759                 if (r_timereport_active)
9760                         R_TimeReport("coronas");
9761         }
9762
9763         // don't let sound skip if going slow
9764         if (r_refdef.scene.extraupdate)
9765                 S_ExtraUpdate ();
9766
9767         R_ResetViewRendering2D();
9768 }
9769
9770 static const unsigned short bboxelements[36] =
9771 {
9772         5, 1, 3, 5, 3, 7,
9773         6, 2, 0, 6, 0, 4,
9774         7, 3, 2, 7, 2, 6,
9775         4, 0, 1, 4, 1, 5,
9776         4, 5, 7, 4, 7, 6,
9777         1, 0, 2, 1, 2, 3,
9778 };
9779
9780 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9781 {
9782         int i;
9783         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9784
9785         RSurf_ActiveWorldEntity();
9786
9787         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9788         GL_DepthMask(false);
9789         GL_DepthRange(0, 1);
9790         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9791         R_Mesh_ResetTextureState();
9792
9793         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9794         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9795         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9796         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9797         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9798         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9799         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9800         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9801         R_FillColors(color4f, 8, cr, cg, cb, ca);
9802         if (r_refdef.fogenabled)
9803         {
9804                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9805                 {
9806                         f1 = RSurf_FogVertex(v);
9807                         f2 = 1 - f1;
9808                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9809                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9810                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9811                 }
9812         }
9813         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9814         R_Mesh_ResetTextureState();
9815         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9816         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9817 }
9818
9819 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9820 {
9821         int i;
9822         float color[4];
9823         prvm_edict_t *edict;
9824         prvm_prog_t *prog_save = prog;
9825
9826         // this function draws bounding boxes of server entities
9827         if (!sv.active)
9828                 return;
9829
9830         GL_CullFace(GL_NONE);
9831         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9832
9833         prog = 0;
9834         SV_VM_Begin();
9835         for (i = 0;i < numsurfaces;i++)
9836         {
9837                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9838                 switch ((int)edict->fields.server->solid)
9839                 {
9840                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9841                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9842                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9843                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9844                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9845                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9846                 }
9847                 color[3] *= r_showbboxes.value;
9848                 color[3] = bound(0, color[3], 1);
9849                 GL_DepthTest(!r_showdisabledepthtest.integer);
9850                 GL_CullFace(r_refdef.view.cullface_front);
9851                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9852         }
9853         SV_VM_End();
9854         prog = prog_save;
9855 }
9856
9857 static void R_DrawEntityBBoxes(void)
9858 {
9859         int i;
9860         prvm_edict_t *edict;
9861         vec3_t center;
9862         prvm_prog_t *prog_save = prog;
9863
9864         // this function draws bounding boxes of server entities
9865         if (!sv.active)
9866                 return;
9867
9868         prog = 0;
9869         SV_VM_Begin();
9870         for (i = 0;i < prog->num_edicts;i++)
9871         {
9872                 edict = PRVM_EDICT_NUM(i);
9873                 if (edict->priv.server->free)
9874                         continue;
9875                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9876                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9877                         continue;
9878                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9879                         continue;
9880                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9881                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9882         }
9883         SV_VM_End();
9884         prog = prog_save;
9885 }
9886
9887 static const int nomodelelement3i[24] =
9888 {
9889         5, 2, 0,
9890         5, 1, 2,
9891         5, 0, 3,
9892         5, 3, 1,
9893         0, 2, 4,
9894         2, 1, 4,
9895         3, 0, 4,
9896         1, 3, 4
9897 };
9898
9899 static const unsigned short nomodelelement3s[24] =
9900 {
9901         5, 2, 0,
9902         5, 1, 2,
9903         5, 0, 3,
9904         5, 3, 1,
9905         0, 2, 4,
9906         2, 1, 4,
9907         3, 0, 4,
9908         1, 3, 4
9909 };
9910
9911 static const float nomodelvertex3f[6*3] =
9912 {
9913         -16,   0,   0,
9914          16,   0,   0,
9915           0, -16,   0,
9916           0,  16,   0,
9917           0,   0, -16,
9918           0,   0,  16
9919 };
9920
9921 static const float nomodelcolor4f[6*4] =
9922 {
9923         0.0f, 0.0f, 0.5f, 1.0f,
9924         0.0f, 0.0f, 0.5f, 1.0f,
9925         0.0f, 0.5f, 0.0f, 1.0f,
9926         0.0f, 0.5f, 0.0f, 1.0f,
9927         0.5f, 0.0f, 0.0f, 1.0f,
9928         0.5f, 0.0f, 0.0f, 1.0f
9929 };
9930
9931 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9932 {
9933         int i;
9934         float f1, f2, *c;
9935         float color4f[6*4];
9936
9937         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);
9938
9939         // this is only called once per entity so numsurfaces is always 1, and
9940         // surfacelist is always {0}, so this code does not handle batches
9941
9942         if (rsurface.ent_flags & RENDER_ADDITIVE)
9943         {
9944                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9945                 GL_DepthMask(false);
9946         }
9947         else if (rsurface.colormod[3] < 1)
9948         {
9949                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9950                 GL_DepthMask(false);
9951         }
9952         else
9953         {
9954                 GL_BlendFunc(GL_ONE, GL_ZERO);
9955                 GL_DepthMask(true);
9956         }
9957         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9958         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9959         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9960         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9961         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9962         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9963         for (i = 0, c = color4f;i < 6;i++, c += 4)
9964         {
9965                 c[0] *= rsurface.colormod[0];
9966                 c[1] *= rsurface.colormod[1];
9967                 c[2] *= rsurface.colormod[2];
9968                 c[3] *= rsurface.colormod[3];
9969         }
9970         if (r_refdef.fogenabled)
9971         {
9972                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9973                 {
9974                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9975                         f2 = 1 - f1;
9976                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9977                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9978                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9979                 }
9980         }
9981         R_Mesh_ResetTextureState();
9982         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9983         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9984 }
9985
9986 void R_DrawNoModel(entity_render_t *ent)
9987 {
9988         vec3_t org;
9989         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9990         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9991                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9992         else
9993                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9994 }
9995
9996 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9997 {
9998         vec3_t right1, right2, diff, normal;
9999
10000         VectorSubtract (org2, org1, normal);
10001
10002         // calculate 'right' vector for start
10003         VectorSubtract (r_refdef.view.origin, org1, diff);
10004         CrossProduct (normal, diff, right1);
10005         VectorNormalize (right1);
10006
10007         // calculate 'right' vector for end
10008         VectorSubtract (r_refdef.view.origin, org2, diff);
10009         CrossProduct (normal, diff, right2);
10010         VectorNormalize (right2);
10011
10012         vert[ 0] = org1[0] + width * right1[0];
10013         vert[ 1] = org1[1] + width * right1[1];
10014         vert[ 2] = org1[2] + width * right1[2];
10015         vert[ 3] = org1[0] - width * right1[0];
10016         vert[ 4] = org1[1] - width * right1[1];
10017         vert[ 5] = org1[2] - width * right1[2];
10018         vert[ 6] = org2[0] - width * right2[0];
10019         vert[ 7] = org2[1] - width * right2[1];
10020         vert[ 8] = org2[2] - width * right2[2];
10021         vert[ 9] = org2[0] + width * right2[0];
10022         vert[10] = org2[1] + width * right2[1];
10023         vert[11] = org2[2] + width * right2[2];
10024 }
10025
10026 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)
10027 {
10028         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10029         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10030         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10031         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10032         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10033         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10034         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10035         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10036         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10037         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10038         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10039         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10040 }
10041
10042 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10043 {
10044         int i;
10045         float *vertex3f;
10046         float v[3];
10047         VectorSet(v, x, y, z);
10048         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10049                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10050                         break;
10051         if (i == mesh->numvertices)
10052         {
10053                 if (mesh->numvertices < mesh->maxvertices)
10054                 {
10055                         VectorCopy(v, vertex3f);
10056                         mesh->numvertices++;
10057                 }
10058                 return mesh->numvertices;
10059         }
10060         else
10061                 return i;
10062 }
10063
10064 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10065 {
10066         int i;
10067         int *e, element[3];
10068         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10069         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10070         e = mesh->element3i + mesh->numtriangles * 3;
10071         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10072         {
10073                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10074                 if (mesh->numtriangles < mesh->maxtriangles)
10075                 {
10076                         *e++ = element[0];
10077                         *e++ = element[1];
10078                         *e++ = element[2];
10079                         mesh->numtriangles++;
10080                 }
10081                 element[1] = element[2];
10082         }
10083 }
10084
10085 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10086 {
10087         int i;
10088         int *e, element[3];
10089         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10090         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10091         e = mesh->element3i + mesh->numtriangles * 3;
10092         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10093         {
10094                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10095                 if (mesh->numtriangles < mesh->maxtriangles)
10096                 {
10097                         *e++ = element[0];
10098                         *e++ = element[1];
10099                         *e++ = element[2];
10100                         mesh->numtriangles++;
10101                 }
10102                 element[1] = element[2];
10103         }
10104 }
10105
10106 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10107 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10108 {
10109         int planenum, planenum2;
10110         int w;
10111         int tempnumpoints;
10112         mplane_t *plane, *plane2;
10113         double maxdist;
10114         double temppoints[2][256*3];
10115         // figure out how large a bounding box we need to properly compute this brush
10116         maxdist = 0;
10117         for (w = 0;w < numplanes;w++)
10118                 maxdist = max(maxdist, fabs(planes[w].dist));
10119         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10120         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10121         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10122         {
10123                 w = 0;
10124                 tempnumpoints = 4;
10125                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10126                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10127                 {
10128                         if (planenum2 == planenum)
10129                                 continue;
10130                         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);
10131                         w = !w;
10132                 }
10133                 if (tempnumpoints < 3)
10134                         continue;
10135                 // generate elements forming a triangle fan for this polygon
10136                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10137         }
10138 }
10139
10140 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)
10141 {
10142         texturelayer_t *layer;
10143         layer = t->currentlayers + t->currentnumlayers++;
10144         layer->type = type;
10145         layer->depthmask = depthmask;
10146         layer->blendfunc1 = blendfunc1;
10147         layer->blendfunc2 = blendfunc2;
10148         layer->texture = texture;
10149         layer->texmatrix = *matrix;
10150         layer->color[0] = r;
10151         layer->color[1] = g;
10152         layer->color[2] = b;
10153         layer->color[3] = a;
10154 }
10155
10156 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10157 {
10158         if(parms[0] == 0 && parms[1] == 0)
10159                 return false;
10160         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10161                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10162                         return false;
10163         return true;
10164 }
10165
10166 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10167 {
10168         double index, f;
10169         index = parms[2] + r_refdef.scene.time * parms[3];
10170         index -= floor(index);
10171         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10172         {
10173         default:
10174         case Q3WAVEFUNC_NONE:
10175         case Q3WAVEFUNC_NOISE:
10176         case Q3WAVEFUNC_COUNT:
10177                 f = 0;
10178                 break;
10179         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10180         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10181         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10182         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10183         case Q3WAVEFUNC_TRIANGLE:
10184                 index *= 4;
10185                 f = index - floor(index);
10186                 if (index < 1)
10187                         f = f;
10188                 else if (index < 2)
10189                         f = 1 - f;
10190                 else if (index < 3)
10191                         f = -f;
10192                 else
10193                         f = -(1 - f);
10194                 break;
10195         }
10196         f = parms[0] + parms[1] * f;
10197         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10198                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10199         return (float) f;
10200 }
10201
10202 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10203 {
10204         int w, h, idx;
10205         float f;
10206         float tcmat[12];
10207         matrix4x4_t matrix, temp;
10208         switch(tcmod->tcmod)
10209         {
10210                 case Q3TCMOD_COUNT:
10211                 case Q3TCMOD_NONE:
10212                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10213                                 matrix = r_waterscrollmatrix;
10214                         else
10215                                 matrix = identitymatrix;
10216                         break;
10217                 case Q3TCMOD_ENTITYTRANSLATE:
10218                         // this is used in Q3 to allow the gamecode to control texcoord
10219                         // scrolling on the entity, which is not supported in darkplaces yet.
10220                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10221                         break;
10222                 case Q3TCMOD_ROTATE:
10223                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10224                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10225                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10226                         break;
10227                 case Q3TCMOD_SCALE:
10228                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10229                         break;
10230                 case Q3TCMOD_SCROLL:
10231                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10232                         break;
10233                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10234                         w = (int) tcmod->parms[0];
10235                         h = (int) tcmod->parms[1];
10236                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10237                         f = f - floor(f);
10238                         idx = (int) floor(f * w * h);
10239                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10240                         break;
10241                 case Q3TCMOD_STRETCH:
10242                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10243                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10244                         break;
10245                 case Q3TCMOD_TRANSFORM:
10246                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10247                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10248                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10249                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10250                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10251                         break;
10252                 case Q3TCMOD_TURBULENT:
10253                         // this is handled in the RSurf_PrepareVertices function
10254                         matrix = identitymatrix;
10255                         break;
10256         }
10257         temp = *texmatrix;
10258         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10259 }
10260
10261 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10262 {
10263         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10264         char name[MAX_QPATH];
10265         skinframe_t *skinframe;
10266         unsigned char pixels[296*194];
10267         strlcpy(cache->name, skinname, sizeof(cache->name));
10268         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10269         if (developer_loading.integer)
10270                 Con_Printf("loading %s\n", name);
10271         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10272         if (!skinframe || !skinframe->base)
10273         {
10274                 unsigned char *f;
10275                 fs_offset_t filesize;
10276                 skinframe = NULL;
10277                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10278                 if (f)
10279                 {
10280                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10281                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10282                         Mem_Free(f);
10283                 }
10284         }
10285         cache->skinframe = skinframe;
10286 }
10287
10288 texture_t *R_GetCurrentTexture(texture_t *t)
10289 {
10290         int i;
10291         const entity_render_t *ent = rsurface.entity;
10292         dp_model_t *model = ent->model;
10293         q3shaderinfo_layer_tcmod_t *tcmod;
10294
10295         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10296                 return t->currentframe;
10297         t->update_lastrenderframe = r_textureframe;
10298         t->update_lastrenderentity = (void *)ent;
10299
10300         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10301                 t->camera_entity = ent->entitynumber;
10302         else
10303                 t->camera_entity = 0;
10304
10305         // switch to an alternate material if this is a q1bsp animated material
10306         {
10307                 texture_t *texture = t;
10308                 int s = rsurface.ent_skinnum;
10309                 if ((unsigned int)s >= (unsigned int)model->numskins)
10310                         s = 0;
10311                 if (model->skinscenes)
10312                 {
10313                         if (model->skinscenes[s].framecount > 1)
10314                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10315                         else
10316                                 s = model->skinscenes[s].firstframe;
10317                 }
10318                 if (s > 0)
10319                         t = t + s * model->num_surfaces;
10320                 if (t->animated)
10321                 {
10322                         // use an alternate animation if the entity's frame is not 0,
10323                         // and only if the texture has an alternate animation
10324                         if (rsurface.ent_alttextures && t->anim_total[1])
10325                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10326                         else
10327                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10328                 }
10329                 texture->currentframe = t;
10330         }
10331
10332         // update currentskinframe to be a qw skin or animation frame
10333         if (rsurface.ent_qwskin >= 0)
10334         {
10335                 i = rsurface.ent_qwskin;
10336                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10337                 {
10338                         r_qwskincache_size = cl.maxclients;
10339                         if (r_qwskincache)
10340                                 Mem_Free(r_qwskincache);
10341                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10342                 }
10343                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10344                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10345                 t->currentskinframe = r_qwskincache[i].skinframe;
10346                 if (t->currentskinframe == NULL)
10347                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10348         }
10349         else if (t->numskinframes >= 2)
10350                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10351         if (t->backgroundnumskinframes >= 2)
10352                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10353
10354         t->currentmaterialflags = t->basematerialflags;
10355         t->currentalpha = rsurface.colormod[3];
10356         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10357                 t->currentalpha *= r_wateralpha.value;
10358         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10359                 t->currentalpha *= t->r_water_wateralpha;
10360         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10361                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10362         if (!(rsurface.ent_flags & RENDER_LIGHT))
10363                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10364         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10365         {
10366                 // pick a model lighting mode
10367                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10368                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10369                 else
10370                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10371         }
10372         if (rsurface.ent_flags & RENDER_ADDITIVE)
10373                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10374         else if (t->currentalpha < 1)
10375                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10376         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10377                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10378         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10379                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10380         if (t->backgroundnumskinframes)
10381                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10382         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10383         {
10384                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10385                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10386         }
10387         else
10388                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10389         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10390                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10391
10392         // there is no tcmod
10393         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10394         {
10395                 t->currenttexmatrix = r_waterscrollmatrix;
10396                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10397         }
10398         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10399         {
10400                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10401                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10402         }
10403
10404         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10405                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10406         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10407                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10408
10409         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10410         if (t->currentskinframe->qpixels)
10411                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10412         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10413         if (!t->basetexture)
10414                 t->basetexture = r_texture_notexture;
10415         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10416         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10417         t->nmaptexture = t->currentskinframe->nmap;
10418         if (!t->nmaptexture)
10419                 t->nmaptexture = r_texture_blanknormalmap;
10420         t->glosstexture = r_texture_black;
10421         t->glowtexture = t->currentskinframe->glow;
10422         t->fogtexture = t->currentskinframe->fog;
10423         t->reflectmasktexture = t->currentskinframe->reflect;
10424         if (t->backgroundnumskinframes)
10425         {
10426                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10427                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10428                 t->backgroundglosstexture = r_texture_black;
10429                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10430                 if (!t->backgroundnmaptexture)
10431                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10432         }
10433         else
10434         {
10435                 t->backgroundbasetexture = r_texture_white;
10436                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10437                 t->backgroundglosstexture = r_texture_black;
10438                 t->backgroundglowtexture = NULL;
10439         }
10440         t->specularpower = r_shadow_glossexponent.value;
10441         // TODO: store reference values for these in the texture?
10442         t->specularscale = 0;
10443         if (r_shadow_gloss.integer > 0)
10444         {
10445                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10446                 {
10447                         if (r_shadow_glossintensity.value > 0)
10448                         {
10449                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10450                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10451                                 t->specularscale = r_shadow_glossintensity.value;
10452                         }
10453                 }
10454                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10455                 {
10456                         t->glosstexture = r_texture_white;
10457                         t->backgroundglosstexture = r_texture_white;
10458                         t->specularscale = r_shadow_gloss2intensity.value;
10459                         t->specularpower = r_shadow_gloss2exponent.value;
10460                 }
10461         }
10462         t->specularscale *= t->specularscalemod;
10463         t->specularpower *= t->specularpowermod;
10464
10465         // lightmaps mode looks bad with dlights using actual texturing, so turn
10466         // off the colormap and glossmap, but leave the normalmap on as it still
10467         // accurately represents the shading involved
10468         if (gl_lightmaps.integer)
10469         {
10470                 t->basetexture = r_texture_grey128;
10471                 t->pantstexture = r_texture_black;
10472                 t->shirttexture = r_texture_black;
10473                 t->nmaptexture = r_texture_blanknormalmap;
10474                 t->glosstexture = r_texture_black;
10475                 t->glowtexture = NULL;
10476                 t->fogtexture = NULL;
10477                 t->reflectmasktexture = NULL;
10478                 t->backgroundbasetexture = NULL;
10479                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10480                 t->backgroundglosstexture = r_texture_black;
10481                 t->backgroundglowtexture = NULL;
10482                 t->specularscale = 0;
10483                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10484         }
10485
10486         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10487         VectorClear(t->dlightcolor);
10488         t->currentnumlayers = 0;
10489         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10490         {
10491                 int blendfunc1, blendfunc2;
10492                 qboolean depthmask;
10493                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10494                 {
10495                         blendfunc1 = GL_SRC_ALPHA;
10496                         blendfunc2 = GL_ONE;
10497                 }
10498                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10499                 {
10500                         blendfunc1 = GL_SRC_ALPHA;
10501                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10502                 }
10503                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10504                 {
10505                         blendfunc1 = t->customblendfunc[0];
10506                         blendfunc2 = t->customblendfunc[1];
10507                 }
10508                 else
10509                 {
10510                         blendfunc1 = GL_ONE;
10511                         blendfunc2 = GL_ZERO;
10512                 }
10513                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10514                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10515                 {
10516                         // fullbright is not affected by r_refdef.lightmapintensity
10517                         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]);
10518                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10519                                 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]);
10520                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10521                                 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]);
10522                 }
10523                 else
10524                 {
10525                         vec3_t ambientcolor;
10526                         float colorscale;
10527                         // set the color tint used for lights affecting this surface
10528                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10529                         colorscale = 2;
10530                         // q3bsp has no lightmap updates, so the lightstylevalue that
10531                         // would normally be baked into the lightmap must be
10532                         // applied to the color
10533                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10534                         if (model->type == mod_brushq3)
10535                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10536                         colorscale *= r_refdef.lightmapintensity;
10537                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10538                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10539                         // basic lit geometry
10540                         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]);
10541                         // add pants/shirt if needed
10542                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10543                                 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]);
10544                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10545                                 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]);
10546                         // now add ambient passes if needed
10547                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10548                         {
10549                                 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]);
10550                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10551                                         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]);
10552                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10553                                         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]);
10554                         }
10555                 }
10556                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10557                         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]);
10558                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10559                 {
10560                         // if this is opaque use alpha blend which will darken the earlier
10561                         // passes cheaply.
10562                         //
10563                         // if this is an alpha blended material, all the earlier passes
10564                         // were darkened by fog already, so we only need to add the fog
10565                         // color ontop through the fog mask texture
10566                         //
10567                         // if this is an additive blended material, all the earlier passes
10568                         // were darkened by fog already, and we should not add fog color
10569                         // (because the background was not darkened, there is no fog color
10570                         // that was lost behind it).
10571                         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]);
10572                 }
10573         }
10574
10575         return t->currentframe;
10576 }
10577
10578 rsurfacestate_t rsurface;
10579
10580 void R_Mesh_ResizeArrays(int newvertices)
10581 {
10582         unsigned char *base;
10583         size_t size;
10584         if (rsurface.array_size >= newvertices)
10585                 return;
10586         if (rsurface.array_base)
10587                 Mem_Free(rsurface.array_base);
10588         rsurface.array_size = (newvertices + 1023) & ~1023;
10589         size = 0;
10590         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10591         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10592         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10593         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10594         size += rsurface.array_size * sizeof(float[3]);
10595         size += rsurface.array_size * sizeof(float[3]);
10596         size += rsurface.array_size * sizeof(float[3]);
10597         size += rsurface.array_size * sizeof(float[3]);
10598         size += rsurface.array_size * sizeof(float[3]);
10599         size += rsurface.array_size * sizeof(float[3]);
10600         size += rsurface.array_size * sizeof(float[3]);
10601         size += rsurface.array_size * sizeof(float[3]);
10602         size += rsurface.array_size * sizeof(float[4]);
10603         size += rsurface.array_size * sizeof(float[2]);
10604         size += rsurface.array_size * sizeof(float[2]);
10605         size += rsurface.array_size * sizeof(float[4]);
10606         size += rsurface.array_size * sizeof(int[3]);
10607         size += rsurface.array_size * sizeof(unsigned short[3]);
10608         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10609         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10610         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10611         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10612         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10613         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10614         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10615         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10616         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10617         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10618         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10619         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10620         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10621         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10622         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10623         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10624         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10625         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10626         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10627 }
10628
10629 void RSurf_ActiveWorldEntity(void)
10630 {
10631         dp_model_t *model = r_refdef.scene.worldmodel;
10632         //if (rsurface.entity == r_refdef.scene.worldentity)
10633         //      return;
10634         rsurface.entity = r_refdef.scene.worldentity;
10635         rsurface.skeleton = NULL;
10636         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10637         rsurface.ent_skinnum = 0;
10638         rsurface.ent_qwskin = -1;
10639         rsurface.ent_shadertime = 0;
10640         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10641         if (rsurface.array_size < model->surfmesh.num_vertices)
10642                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10643         rsurface.matrix = identitymatrix;
10644         rsurface.inversematrix = identitymatrix;
10645         rsurface.matrixscale = 1;
10646         rsurface.inversematrixscale = 1;
10647         R_EntityMatrix(&identitymatrix);
10648         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10649         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10650         rsurface.fograngerecip = r_refdef.fograngerecip;
10651         rsurface.fogheightfade = r_refdef.fogheightfade;
10652         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10653         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10654         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10655         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10656         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10657         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10658         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10659         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10660         rsurface.colormod[3] = 1;
10661         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);
10662         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10663         rsurface.frameblend[0].lerp = 1;
10664         rsurface.ent_alttextures = false;
10665         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10666         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10667         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10668         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10669         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10670         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10671         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10672         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10673         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10674         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10675         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10676         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10677         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10678         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10679         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10680         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10681         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10682         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10683         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10684         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10685         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10686         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10687         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10688         rsurface.modelelement3i = model->surfmesh.data_element3i;
10689         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10690         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10691         rsurface.modelelement3s = model->surfmesh.data_element3s;
10692         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10693         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10694         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10695         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10696         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10697         rsurface.modelsurfaces = model->data_surfaces;
10698         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10699         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10700         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10701         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10702         rsurface.modelgeneratedvertex = false;
10703         rsurface.batchgeneratedvertex = false;
10704         rsurface.batchfirstvertex = 0;
10705         rsurface.batchnumvertices = 0;
10706         rsurface.batchfirsttriangle = 0;
10707         rsurface.batchnumtriangles = 0;
10708         rsurface.batchvertex3f  = NULL;
10709         rsurface.batchvertex3f_vertexbuffer = NULL;
10710         rsurface.batchvertex3f_bufferoffset = 0;
10711         rsurface.batchsvector3f = NULL;
10712         rsurface.batchsvector3f_vertexbuffer = NULL;
10713         rsurface.batchsvector3f_bufferoffset = 0;
10714         rsurface.batchtvector3f = NULL;
10715         rsurface.batchtvector3f_vertexbuffer = NULL;
10716         rsurface.batchtvector3f_bufferoffset = 0;
10717         rsurface.batchnormal3f  = NULL;
10718         rsurface.batchnormal3f_vertexbuffer = NULL;
10719         rsurface.batchnormal3f_bufferoffset = 0;
10720         rsurface.batchlightmapcolor4f = NULL;
10721         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10722         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10723         rsurface.batchtexcoordtexture2f = NULL;
10724         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10725         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10726         rsurface.batchtexcoordlightmap2f = NULL;
10727         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10728         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10729         rsurface.batchvertexmesh = NULL;
10730         rsurface.batchvertexmeshbuffer = NULL;
10731         rsurface.batchvertexposition = NULL;
10732         rsurface.batchvertexpositionbuffer = NULL;
10733         rsurface.batchelement3i = NULL;
10734         rsurface.batchelement3i_indexbuffer = NULL;
10735         rsurface.batchelement3i_bufferoffset = 0;
10736         rsurface.batchelement3s = NULL;
10737         rsurface.batchelement3s_indexbuffer = NULL;
10738         rsurface.batchelement3s_bufferoffset = 0;
10739         rsurface.passcolor4f = NULL;
10740         rsurface.passcolor4f_vertexbuffer = NULL;
10741         rsurface.passcolor4f_bufferoffset = 0;
10742 }
10743
10744 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10745 {
10746         dp_model_t *model = ent->model;
10747         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10748         //      return;
10749         rsurface.entity = (entity_render_t *)ent;
10750         rsurface.skeleton = ent->skeleton;
10751         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10752         rsurface.ent_skinnum = ent->skinnum;
10753         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;
10754         rsurface.ent_shadertime = ent->shadertime;
10755         rsurface.ent_flags = ent->flags;
10756         if (rsurface.array_size < model->surfmesh.num_vertices)
10757                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10758         rsurface.matrix = ent->matrix;
10759         rsurface.inversematrix = ent->inversematrix;
10760         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10761         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10762         R_EntityMatrix(&rsurface.matrix);
10763         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10764         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10765         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10766         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10767         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10768         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10769         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10770         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10771         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10772         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10773         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10774         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10775         rsurface.colormod[3] = ent->alpha;
10776         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10777         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10778         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10779         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10780         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10781         if (ent->model->brush.submodel && !prepass)
10782         {
10783                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10784                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10785         }
10786         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10787         {
10788                 if (ent->animcache_vertex3f && !r_framedata_failed)
10789                 {
10790                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10791                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10792                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10793                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10794                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10795                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10796                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10797                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10798                 }
10799                 else if (wanttangents)
10800                 {
10801                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10802                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10803                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10804                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10805                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10806                         rsurface.modelvertexmesh = NULL;
10807                         rsurface.modelvertexmeshbuffer = NULL;
10808                         rsurface.modelvertexposition = NULL;
10809                         rsurface.modelvertexpositionbuffer = NULL;
10810                 }
10811                 else if (wantnormals)
10812                 {
10813                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10814                         rsurface.modelsvector3f = NULL;
10815                         rsurface.modeltvector3f = NULL;
10816                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10817                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10818                         rsurface.modelvertexmesh = NULL;
10819                         rsurface.modelvertexmeshbuffer = NULL;
10820                         rsurface.modelvertexposition = NULL;
10821                         rsurface.modelvertexpositionbuffer = NULL;
10822                 }
10823                 else
10824                 {
10825                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10826                         rsurface.modelsvector3f = NULL;
10827                         rsurface.modeltvector3f = NULL;
10828                         rsurface.modelnormal3f = NULL;
10829                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10830                         rsurface.modelvertexmesh = NULL;
10831                         rsurface.modelvertexmeshbuffer = NULL;
10832                         rsurface.modelvertexposition = NULL;
10833                         rsurface.modelvertexpositionbuffer = NULL;
10834                 }
10835                 rsurface.modelvertex3f_vertexbuffer = 0;
10836                 rsurface.modelvertex3f_bufferoffset = 0;
10837                 rsurface.modelsvector3f_vertexbuffer = 0;
10838                 rsurface.modelsvector3f_bufferoffset = 0;
10839                 rsurface.modeltvector3f_vertexbuffer = 0;
10840                 rsurface.modeltvector3f_bufferoffset = 0;
10841                 rsurface.modelnormal3f_vertexbuffer = 0;
10842                 rsurface.modelnormal3f_bufferoffset = 0;
10843                 rsurface.modelgeneratedvertex = true;
10844         }
10845         else
10846         {
10847                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10848                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10849                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10850                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10851                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10852                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10853                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10854                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10855                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10856                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10857                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10858                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10859                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10860                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10861                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10862                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10863                 rsurface.modelgeneratedvertex = false;
10864         }
10865         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10866         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10867         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10868         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10869         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10870         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10871         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10872         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10873         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10874         rsurface.modelelement3i = model->surfmesh.data_element3i;
10875         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10876         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10877         rsurface.modelelement3s = model->surfmesh.data_element3s;
10878         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10879         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10880         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10881         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10882         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10883         rsurface.modelsurfaces = model->data_surfaces;
10884         rsurface.batchgeneratedvertex = false;
10885         rsurface.batchfirstvertex = 0;
10886         rsurface.batchnumvertices = 0;
10887         rsurface.batchfirsttriangle = 0;
10888         rsurface.batchnumtriangles = 0;
10889         rsurface.batchvertex3f  = NULL;
10890         rsurface.batchvertex3f_vertexbuffer = NULL;
10891         rsurface.batchvertex3f_bufferoffset = 0;
10892         rsurface.batchsvector3f = NULL;
10893         rsurface.batchsvector3f_vertexbuffer = NULL;
10894         rsurface.batchsvector3f_bufferoffset = 0;
10895         rsurface.batchtvector3f = NULL;
10896         rsurface.batchtvector3f_vertexbuffer = NULL;
10897         rsurface.batchtvector3f_bufferoffset = 0;
10898         rsurface.batchnormal3f  = NULL;
10899         rsurface.batchnormal3f_vertexbuffer = NULL;
10900         rsurface.batchnormal3f_bufferoffset = 0;
10901         rsurface.batchlightmapcolor4f = NULL;
10902         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10903         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10904         rsurface.batchtexcoordtexture2f = NULL;
10905         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10906         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10907         rsurface.batchtexcoordlightmap2f = NULL;
10908         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10909         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10910         rsurface.batchvertexmesh = NULL;
10911         rsurface.batchvertexmeshbuffer = NULL;
10912         rsurface.batchvertexposition = NULL;
10913         rsurface.batchvertexpositionbuffer = NULL;
10914         rsurface.batchelement3i = NULL;
10915         rsurface.batchelement3i_indexbuffer = NULL;
10916         rsurface.batchelement3i_bufferoffset = 0;
10917         rsurface.batchelement3s = NULL;
10918         rsurface.batchelement3s_indexbuffer = NULL;
10919         rsurface.batchelement3s_bufferoffset = 0;
10920         rsurface.passcolor4f = NULL;
10921         rsurface.passcolor4f_vertexbuffer = NULL;
10922         rsurface.passcolor4f_bufferoffset = 0;
10923 }
10924
10925 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)
10926 {
10927         int i;
10928
10929         rsurface.entity = r_refdef.scene.worldentity;
10930         rsurface.skeleton = NULL;
10931         rsurface.ent_skinnum = 0;
10932         rsurface.ent_qwskin = -1;
10933         rsurface.ent_shadertime = shadertime;
10934         rsurface.ent_flags = entflags;
10935         rsurface.modelnumvertices = numvertices;
10936         rsurface.modelnumtriangles = numtriangles;
10937         if (rsurface.array_size < rsurface.modelnumvertices)
10938                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10939         rsurface.matrix = *matrix;
10940         rsurface.inversematrix = *inversematrix;
10941         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10942         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10943         R_EntityMatrix(&rsurface.matrix);
10944         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10945         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10946         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10947         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10948         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10949         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10950         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10951         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10952         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10953         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10954         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10955         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10956         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);
10957         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10958         rsurface.frameblend[0].lerp = 1;
10959         rsurface.ent_alttextures = false;
10960         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10961         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10962         if (wanttangents)
10963         {
10964                 rsurface.modelvertex3f = vertex3f;
10965                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10966                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10967                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10968         }
10969         else if (wantnormals)
10970         {
10971                 rsurface.modelvertex3f = vertex3f;
10972                 rsurface.modelsvector3f = NULL;
10973                 rsurface.modeltvector3f = NULL;
10974                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10975         }
10976         else
10977         {
10978                 rsurface.modelvertex3f = vertex3f;
10979                 rsurface.modelsvector3f = NULL;
10980                 rsurface.modeltvector3f = NULL;
10981                 rsurface.modelnormal3f = NULL;
10982         }
10983         rsurface.modelvertexmesh = NULL;
10984         rsurface.modelvertexmeshbuffer = NULL;
10985         rsurface.modelvertexposition = NULL;
10986         rsurface.modelvertexpositionbuffer = NULL;
10987         rsurface.modelvertex3f_vertexbuffer = 0;
10988         rsurface.modelvertex3f_bufferoffset = 0;
10989         rsurface.modelsvector3f_vertexbuffer = 0;
10990         rsurface.modelsvector3f_bufferoffset = 0;
10991         rsurface.modeltvector3f_vertexbuffer = 0;
10992         rsurface.modeltvector3f_bufferoffset = 0;
10993         rsurface.modelnormal3f_vertexbuffer = 0;
10994         rsurface.modelnormal3f_bufferoffset = 0;
10995         rsurface.modelgeneratedvertex = true;
10996         rsurface.modellightmapcolor4f  = color4f;
10997         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10998         rsurface.modellightmapcolor4f_bufferoffset = 0;
10999         rsurface.modeltexcoordtexture2f  = texcoord2f;
11000         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11001         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11002         rsurface.modeltexcoordlightmap2f  = NULL;
11003         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11004         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11005         rsurface.modelelement3i = element3i;
11006         rsurface.modelelement3i_indexbuffer = NULL;
11007         rsurface.modelelement3i_bufferoffset = 0;
11008         rsurface.modelelement3s = element3s;
11009         rsurface.modelelement3s_indexbuffer = NULL;
11010         rsurface.modelelement3s_bufferoffset = 0;
11011         rsurface.modellightmapoffsets = NULL;
11012         rsurface.modelsurfaces = NULL;
11013         rsurface.batchgeneratedvertex = false;
11014         rsurface.batchfirstvertex = 0;
11015         rsurface.batchnumvertices = 0;
11016         rsurface.batchfirsttriangle = 0;
11017         rsurface.batchnumtriangles = 0;
11018         rsurface.batchvertex3f  = NULL;
11019         rsurface.batchvertex3f_vertexbuffer = NULL;
11020         rsurface.batchvertex3f_bufferoffset = 0;
11021         rsurface.batchsvector3f = NULL;
11022         rsurface.batchsvector3f_vertexbuffer = NULL;
11023         rsurface.batchsvector3f_bufferoffset = 0;
11024         rsurface.batchtvector3f = NULL;
11025         rsurface.batchtvector3f_vertexbuffer = NULL;
11026         rsurface.batchtvector3f_bufferoffset = 0;
11027         rsurface.batchnormal3f  = NULL;
11028         rsurface.batchnormal3f_vertexbuffer = NULL;
11029         rsurface.batchnormal3f_bufferoffset = 0;
11030         rsurface.batchlightmapcolor4f = NULL;
11031         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11032         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11033         rsurface.batchtexcoordtexture2f = NULL;
11034         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11035         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11036         rsurface.batchtexcoordlightmap2f = NULL;
11037         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11038         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11039         rsurface.batchvertexmesh = NULL;
11040         rsurface.batchvertexmeshbuffer = NULL;
11041         rsurface.batchvertexposition = NULL;
11042         rsurface.batchvertexpositionbuffer = NULL;
11043         rsurface.batchelement3i = NULL;
11044         rsurface.batchelement3i_indexbuffer = NULL;
11045         rsurface.batchelement3i_bufferoffset = 0;
11046         rsurface.batchelement3s = NULL;
11047         rsurface.batchelement3s_indexbuffer = NULL;
11048         rsurface.batchelement3s_bufferoffset = 0;
11049         rsurface.passcolor4f = NULL;
11050         rsurface.passcolor4f_vertexbuffer = NULL;
11051         rsurface.passcolor4f_bufferoffset = 0;
11052
11053         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11054         {
11055                 if ((wantnormals || wanttangents) && !normal3f)
11056                 {
11057                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11058                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11059                 }
11060                 if (wanttangents && !svector3f)
11061                 {
11062                         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);
11063                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11064                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11065                 }
11066         }
11067
11068         // now convert arrays into vertexmesh structs
11069         for (i = 0;i < numvertices;i++)
11070         {
11071                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11072                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11073                 if (rsurface.modelsvector3f)
11074                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11075                 if (rsurface.modeltvector3f)
11076                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11077                 if (rsurface.modelnormal3f)
11078                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11079                 if (rsurface.modellightmapcolor4f)
11080                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11081                 if (rsurface.modeltexcoordtexture2f)
11082                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11083                 if (rsurface.modeltexcoordlightmap2f)
11084                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11085         }
11086 }
11087
11088 float RSurf_FogPoint(const float *v)
11089 {
11090         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11091         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11092         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11093         float FogHeightFade = r_refdef.fogheightfade;
11094         float fogfrac;
11095         unsigned int fogmasktableindex;
11096         if (r_refdef.fogplaneviewabove)
11097                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11098         else
11099                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11100         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11101         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11102 }
11103
11104 float RSurf_FogVertex(const float *v)
11105 {
11106         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11107         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11108         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11109         float FogHeightFade = rsurface.fogheightfade;
11110         float fogfrac;
11111         unsigned int fogmasktableindex;
11112         if (r_refdef.fogplaneviewabove)
11113                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11114         else
11115                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11116         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11117         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11118 }
11119
11120 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11121 {
11122         int i;
11123         for (i = 0;i < numelements;i++)
11124                 outelement3i[i] = inelement3i[i] + adjust;
11125 }
11126
11127 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11128 extern cvar_t gl_vbo;
11129 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11130 {
11131         int deformindex;
11132         int firsttriangle;
11133         int numtriangles;
11134         int firstvertex;
11135         int endvertex;
11136         int numvertices;
11137         int surfacefirsttriangle;
11138         int surfacenumtriangles;
11139         int surfacefirstvertex;
11140         int surfaceendvertex;
11141         int surfacenumvertices;
11142         int surfaceadjustvertex;
11143         int needsupdate;
11144         int i, j;
11145         qboolean gaps;
11146         qboolean dynamicvertex;
11147         float amplitude;
11148         float animpos;
11149         float scale;
11150         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11151         float waveparms[4];
11152         q3shaderinfo_deform_t *deform;
11153         const msurface_t *surface, *firstsurface;
11154         r_vertexposition_t *vertexposition;
11155         r_vertexmesh_t *vertexmesh;
11156         if (!texturenumsurfaces)
11157                 return;
11158         // find vertex range of this surface batch
11159         gaps = false;
11160         firstsurface = texturesurfacelist[0];
11161         firsttriangle = firstsurface->num_firsttriangle;
11162         numtriangles = 0;
11163         firstvertex = endvertex = firstsurface->num_firstvertex;
11164         for (i = 0;i < texturenumsurfaces;i++)
11165         {
11166                 surface = texturesurfacelist[i];
11167                 if (surface != firstsurface + i)
11168                         gaps = true;
11169                 surfacefirstvertex = surface->num_firstvertex;
11170                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11171                 surfacenumtriangles = surface->num_triangles;
11172                 if (firstvertex > surfacefirstvertex)
11173                         firstvertex = surfacefirstvertex;
11174                 if (endvertex < surfaceendvertex)
11175                         endvertex = surfaceendvertex;
11176                 numtriangles += surfacenumtriangles;
11177         }
11178         if (!numtriangles)
11179                 return;
11180
11181         // we now know the vertex range used, and if there are any gaps in it
11182         rsurface.batchfirstvertex = firstvertex;
11183         rsurface.batchnumvertices = endvertex - firstvertex;
11184         rsurface.batchfirsttriangle = firsttriangle;
11185         rsurface.batchnumtriangles = numtriangles;
11186
11187         // this variable holds flags for which properties have been updated that
11188         // may require regenerating vertexmesh or vertexposition arrays...
11189         needsupdate = 0;
11190
11191         // check if any dynamic vertex processing must occur
11192         dynamicvertex = false;
11193
11194         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11195                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11196         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11197         {
11198                 switch (deform->deform)
11199                 {
11200                 default:
11201                 case Q3DEFORM_PROJECTIONSHADOW:
11202                 case Q3DEFORM_TEXT0:
11203                 case Q3DEFORM_TEXT1:
11204                 case Q3DEFORM_TEXT2:
11205                 case Q3DEFORM_TEXT3:
11206                 case Q3DEFORM_TEXT4:
11207                 case Q3DEFORM_TEXT5:
11208                 case Q3DEFORM_TEXT6:
11209                 case Q3DEFORM_TEXT7:
11210                 case Q3DEFORM_NONE:
11211                         break;
11212                 case Q3DEFORM_AUTOSPRITE:
11213                         dynamicvertex = true;
11214                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11215                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11216                         break;
11217                 case Q3DEFORM_AUTOSPRITE2:
11218                         dynamicvertex = true;
11219                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11220                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11221                         break;
11222                 case Q3DEFORM_NORMAL:
11223                         dynamicvertex = true;
11224                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11225                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11226                         break;
11227                 case Q3DEFORM_WAVE:
11228                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11229                                 break; // if wavefunc is a nop, ignore this transform
11230                         dynamicvertex = true;
11231                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11232                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11233                         break;
11234                 case Q3DEFORM_BULGE:
11235                         dynamicvertex = true;
11236                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11237                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11238                         break;
11239                 case Q3DEFORM_MOVE:
11240                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11241                                 break; // if wavefunc is a nop, ignore this transform
11242                         dynamicvertex = true;
11243                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11244                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11245                         break;
11246                 }
11247         }
11248         switch(rsurface.texture->tcgen.tcgen)
11249         {
11250         default:
11251         case Q3TCGEN_TEXTURE:
11252                 break;
11253         case Q3TCGEN_LIGHTMAP:
11254                 dynamicvertex = true;
11255                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11256                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11257                 break;
11258         case Q3TCGEN_VECTOR:
11259                 dynamicvertex = true;
11260                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11261                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11262                 break;
11263         case Q3TCGEN_ENVIRONMENT:
11264                 dynamicvertex = true;
11265                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11266                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11267                 break;
11268         }
11269         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11270         {
11271                 dynamicvertex = true;
11272                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11273                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11274         }
11275
11276         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11277         {
11278                 dynamicvertex = true;
11279                 batchneed |= BATCHNEED_NOGAPS;
11280                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11281         }
11282
11283         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11284         {
11285                 dynamicvertex = true;
11286                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11287                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11288         }
11289
11290         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11291         {
11292                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11293                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11294                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11295                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11296                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11297                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11298                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11299         }
11300
11301         // when the model data has no vertex buffer (dynamic mesh), we need to
11302         // eliminate gaps
11303         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
11304                 batchneed |= BATCHNEED_NOGAPS;
11305
11306         // if needsupdate, we have to do a dynamic vertex batch for sure
11307         if (needsupdate & batchneed)
11308                 dynamicvertex = true;
11309
11310         // see if we need to build vertexmesh from arrays
11311         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11312                 dynamicvertex = true;
11313
11314         // see if we need to build vertexposition from arrays
11315         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11316                 dynamicvertex = true;
11317
11318         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11319         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11320                 dynamicvertex = true;
11321
11322         // if there is a chance of animated vertex colors, it's a dynamic batch
11323         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11324                 dynamicvertex = true;
11325
11326         rsurface.batchvertex3f = rsurface.modelvertex3f;
11327         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11328         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11329         rsurface.batchsvector3f = rsurface.modelsvector3f;
11330         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11331         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11332         rsurface.batchtvector3f = rsurface.modeltvector3f;
11333         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11334         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11335         rsurface.batchnormal3f = rsurface.modelnormal3f;
11336         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11337         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11338         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11339         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11340         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11341         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11342         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11343         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11344         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11345         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11346         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11347         rsurface.batchvertexposition = rsurface.modelvertexposition;
11348         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11349         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11350         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11351         rsurface.batchelement3i = rsurface.modelelement3i;
11352         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11353         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11354         rsurface.batchelement3s = rsurface.modelelement3s;
11355         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11356         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11357
11358         // if any dynamic vertex processing has to occur in software, we copy the
11359         // entire surface list together before processing to rebase the vertices
11360         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11361         //
11362         // if any gaps exist and we do not have a static vertex buffer, we have to
11363         // copy the surface list together to avoid wasting upload bandwidth on the
11364         // vertices in the gaps.
11365         //
11366         // if gaps exist and we have a static vertex buffer, we still have to
11367         // combine the index buffer ranges into one dynamic index buffer.
11368         //
11369         // in all cases we end up with data that can be drawn in one call.
11370
11371         if (!dynamicvertex)
11372         {
11373                 // static vertex data, just set pointers...
11374                 rsurface.batchgeneratedvertex = false;
11375                 // if there are gaps, we want to build a combined index buffer,
11376                 // otherwise use the original static buffer with an appropriate offset
11377                 if (gaps)
11378                 {
11379                         firsttriangle = 0;
11380                         numtriangles = 0;
11381                         for (i = 0;i < texturenumsurfaces;i++)
11382                         {
11383                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11384                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11385                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11386                                 numtriangles += surfacenumtriangles;
11387                         }
11388                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11389                         rsurface.batchelement3i_indexbuffer = NULL;
11390                         rsurface.batchelement3i_bufferoffset = 0;
11391                         rsurface.batchelement3s = NULL;
11392                         rsurface.batchelement3s_indexbuffer = NULL;
11393                         rsurface.batchelement3s_bufferoffset = 0;
11394                         if (endvertex <= 65536)
11395                         {
11396                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11397                                 for (i = 0;i < numtriangles*3;i++)
11398                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11399                         }
11400                         rsurface.batchfirsttriangle = firsttriangle;
11401                         rsurface.batchnumtriangles = numtriangles;
11402                 }
11403                 return;
11404         }
11405
11406         // something needs software processing, do it for real...
11407         // we only directly handle interleaved array data in this case...
11408         rsurface.batchgeneratedvertex = true;
11409
11410         // now copy the vertex data into a combined array and make an index array
11411         // (this is what Quake3 does all the time)
11412         //if (gaps || rsurface.batchfirstvertex)
11413         {
11414                 rsurface.batchvertexposition = NULL;
11415                 rsurface.batchvertexpositionbuffer = NULL;
11416                 rsurface.batchvertexmesh = NULL;
11417                 rsurface.batchvertexmeshbuffer = NULL;
11418                 rsurface.batchvertex3f = NULL;
11419                 rsurface.batchvertex3f_vertexbuffer = NULL;
11420                 rsurface.batchvertex3f_bufferoffset = 0;
11421                 rsurface.batchsvector3f = NULL;
11422                 rsurface.batchsvector3f_vertexbuffer = NULL;
11423                 rsurface.batchsvector3f_bufferoffset = 0;
11424                 rsurface.batchtvector3f = NULL;
11425                 rsurface.batchtvector3f_vertexbuffer = NULL;
11426                 rsurface.batchtvector3f_bufferoffset = 0;
11427                 rsurface.batchnormal3f = NULL;
11428                 rsurface.batchnormal3f_vertexbuffer = NULL;
11429                 rsurface.batchnormal3f_bufferoffset = 0;
11430                 rsurface.batchlightmapcolor4f = NULL;
11431                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11432                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11433                 rsurface.batchtexcoordtexture2f = NULL;
11434                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11435                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11436                 rsurface.batchtexcoordlightmap2f = NULL;
11437                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11438                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11439                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11440                 rsurface.batchelement3i_indexbuffer = NULL;
11441                 rsurface.batchelement3i_bufferoffset = 0;
11442                 rsurface.batchelement3s = NULL;
11443                 rsurface.batchelement3s_indexbuffer = NULL;
11444                 rsurface.batchelement3s_bufferoffset = 0;
11445                 // we'll only be setting up certain arrays as needed
11446                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11447                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11448                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11449                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11450                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11451                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11452                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11453                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11454                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11455                 {
11456                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11457                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11458                 }
11459                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11460                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11461                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11462                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11463                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11464                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11465                 numvertices = 0;
11466                 numtriangles = 0;
11467                 for (i = 0;i < texturenumsurfaces;i++)
11468                 {
11469                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11470                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11471                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11472                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11473                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11474                         // copy only the data requested
11475                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11476                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11477                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11478                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11479                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11480                         {
11481                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11482                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11483                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11484                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11485                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11486                                 {
11487                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11488                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11489                                 }
11490                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11491                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11492                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11493                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11494                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11495                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11496                         }
11497                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11498                         numvertices += surfacenumvertices;
11499                         numtriangles += surfacenumtriangles;
11500                 }
11501
11502                 // generate a 16bit index array as well if possible
11503                 // (in general, dynamic batches fit)
11504                 if (numvertices <= 65536)
11505                 {
11506                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11507                         for (i = 0;i < numtriangles*3;i++)
11508                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11509                 }
11510
11511                 // since we've copied everything, the batch now starts at 0
11512                 rsurface.batchfirstvertex = 0;
11513                 rsurface.batchnumvertices = numvertices;
11514                 rsurface.batchfirsttriangle = 0;
11515                 rsurface.batchnumtriangles = numtriangles;
11516         }
11517
11518         // q1bsp surfaces rendered in vertex color mode have to have colors
11519         // calculated based on lightstyles
11520         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11521         {
11522                 // generate color arrays for the surfaces in this list
11523                 int c[4];
11524                 int scale;
11525                 int size3;
11526                 const int *offsets;
11527                 const unsigned char *lm;
11528                 numvertices = 0;
11529                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11530                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11531                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11532                 for (i = 0;i < texturenumsurfaces;i++)
11533                 {
11534                         surface = texturesurfacelist[i];
11535                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11536                         surfacenumvertices = surface->num_vertices;
11537                         if (surface->lightmapinfo->samples)
11538                         {
11539                                 for (j = 0;j < surfacenumvertices;j++)
11540                                 {
11541                                         lm = surface->lightmapinfo->samples + offsets[j];
11542                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11543                                         VectorScale(lm, scale, c);
11544                                         if (surface->lightmapinfo->styles[1] != 255)
11545                                         {
11546                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11547                                                 lm += size3;
11548                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11549                                                 VectorMA(c, scale, lm, c);
11550                                                 if (surface->lightmapinfo->styles[2] != 255)
11551                                                 {
11552                                                         lm += size3;
11553                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11554                                                         VectorMA(c, scale, lm, c);
11555                                                         if (surface->lightmapinfo->styles[3] != 255)
11556                                                         {
11557                                                                 lm += size3;
11558                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11559                                                                 VectorMA(c, scale, lm, c);
11560                                                         }
11561                                                 }
11562                                         }
11563                                         c[0] >>= 15;
11564                                         c[1] >>= 15;
11565                                         c[2] >>= 15;
11566                                         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);
11567                                         numvertices++;
11568                                 }
11569                         }
11570                         else
11571                         {
11572                                 for (j = 0;j < surfacenumvertices;j++)
11573                                 {
11574                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11575                                         numvertices++;
11576                                 }
11577                         }
11578                 }
11579         }
11580
11581         // if vertices are deformed (sprite flares and things in maps, possibly
11582         // water waves, bulges and other deformations), modify the copied vertices
11583         // in place
11584         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11585         {
11586                 switch (deform->deform)
11587                 {
11588                 default:
11589                 case Q3DEFORM_PROJECTIONSHADOW:
11590                 case Q3DEFORM_TEXT0:
11591                 case Q3DEFORM_TEXT1:
11592                 case Q3DEFORM_TEXT2:
11593                 case Q3DEFORM_TEXT3:
11594                 case Q3DEFORM_TEXT4:
11595                 case Q3DEFORM_TEXT5:
11596                 case Q3DEFORM_TEXT6:
11597                 case Q3DEFORM_TEXT7:
11598                 case Q3DEFORM_NONE:
11599                         break;
11600                 case Q3DEFORM_AUTOSPRITE:
11601                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11602                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11603                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11604                         VectorNormalize(newforward);
11605                         VectorNormalize(newright);
11606                         VectorNormalize(newup);
11607                         // a single autosprite surface can contain multiple sprites...
11608                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11609                         {
11610                                 VectorClear(center);
11611                                 for (i = 0;i < 4;i++)
11612                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11613                                 VectorScale(center, 0.25f, center);
11614                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11615                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11616                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11617                                 for (i = 0;i < 4;i++)
11618                                 {
11619                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11620                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11621                                 }
11622                         }
11623                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11624                         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);
11625                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11626                         rsurface.batchvertex3f_vertexbuffer = NULL;
11627                         rsurface.batchvertex3f_bufferoffset = 0;
11628                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11629                         rsurface.batchsvector3f_vertexbuffer = NULL;
11630                         rsurface.batchsvector3f_bufferoffset = 0;
11631                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11632                         rsurface.batchtvector3f_vertexbuffer = NULL;
11633                         rsurface.batchtvector3f_bufferoffset = 0;
11634                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11635                         rsurface.batchnormal3f_vertexbuffer = NULL;
11636                         rsurface.batchnormal3f_bufferoffset = 0;
11637                         break;
11638                 case Q3DEFORM_AUTOSPRITE2:
11639                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11640                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11641                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11642                         VectorNormalize(newforward);
11643                         VectorNormalize(newright);
11644                         VectorNormalize(newup);
11645                         {
11646                                 const float *v1, *v2;
11647                                 vec3_t start, end;
11648                                 float f, l;
11649                                 struct
11650                                 {
11651                                         float length2;
11652                                         const float *v1;
11653                                         const float *v2;
11654                                 }
11655                                 shortest[2];
11656                                 memset(shortest, 0, sizeof(shortest));
11657                                 // a single autosprite surface can contain multiple sprites...
11658                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11659                                 {
11660                                         VectorClear(center);
11661                                         for (i = 0;i < 4;i++)
11662                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11663                                         VectorScale(center, 0.25f, center);
11664                                         // find the two shortest edges, then use them to define the
11665                                         // axis vectors for rotating around the central axis
11666                                         for (i = 0;i < 6;i++)
11667                                         {
11668                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11669                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11670                                                 l = VectorDistance2(v1, v2);
11671                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11672                                                 if (v1[2] != v2[2])
11673                                                         l += (1.0f / 1024.0f);
11674                                                 if (shortest[0].length2 > l || i == 0)
11675                                                 {
11676                                                         shortest[1] = shortest[0];
11677                                                         shortest[0].length2 = l;
11678                                                         shortest[0].v1 = v1;
11679                                                         shortest[0].v2 = v2;
11680                                                 }
11681                                                 else if (shortest[1].length2 > l || i == 1)
11682                                                 {
11683                                                         shortest[1].length2 = l;
11684                                                         shortest[1].v1 = v1;
11685                                                         shortest[1].v2 = v2;
11686                                                 }
11687                                         }
11688                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11689                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11690                                         // this calculates the right vector from the shortest edge
11691                                         // and the up vector from the edge midpoints
11692                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11693                                         VectorNormalize(right);
11694                                         VectorSubtract(end, start, up);
11695                                         VectorNormalize(up);
11696                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11697                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11698                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11699                                         VectorNegate(forward, forward);
11700                                         VectorReflect(forward, 0, up, forward);
11701                                         VectorNormalize(forward);
11702                                         CrossProduct(up, forward, newright);
11703                                         VectorNormalize(newright);
11704                                         // rotate the quad around the up axis vector, this is made
11705                                         // especially easy by the fact we know the quad is flat,
11706                                         // so we only have to subtract the center position and
11707                                         // measure distance along the right vector, and then
11708                                         // multiply that by the newright vector and add back the
11709                                         // center position
11710                                         // we also need to subtract the old position to undo the
11711                                         // displacement from the center, which we do with a
11712                                         // DotProduct, the subtraction/addition of center is also
11713                                         // optimized into DotProducts here
11714                                         l = DotProduct(right, center);
11715                                         for (i = 0;i < 4;i++)
11716                                         {
11717                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11718                                                 f = DotProduct(right, v1) - l;
11719                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11720                                         }
11721                                 }
11722                         }
11723                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11724                         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);
11725                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11726                         rsurface.batchvertex3f_vertexbuffer = NULL;
11727                         rsurface.batchvertex3f_bufferoffset = 0;
11728                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11729                         rsurface.batchsvector3f_vertexbuffer = NULL;
11730                         rsurface.batchsvector3f_bufferoffset = 0;
11731                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11732                         rsurface.batchtvector3f_vertexbuffer = NULL;
11733                         rsurface.batchtvector3f_bufferoffset = 0;
11734                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11735                         rsurface.batchnormal3f_vertexbuffer = NULL;
11736                         rsurface.batchnormal3f_bufferoffset = 0;
11737                         break;
11738                 case Q3DEFORM_NORMAL:
11739                         // deform the normals to make reflections wavey
11740                         for (j = 0;j < rsurface.batchnumvertices;j++)
11741                         {
11742                                 float vertex[3];
11743                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11744                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11745                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11746                                 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]);
11747                                 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]);
11748                                 VectorNormalize(normal);
11749                         }
11750                         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);
11751                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11752                         rsurface.batchsvector3f_vertexbuffer = NULL;
11753                         rsurface.batchsvector3f_bufferoffset = 0;
11754                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11755                         rsurface.batchtvector3f_vertexbuffer = NULL;
11756                         rsurface.batchtvector3f_bufferoffset = 0;
11757                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11758                         rsurface.batchnormal3f_vertexbuffer = NULL;
11759                         rsurface.batchnormal3f_bufferoffset = 0;
11760                         break;
11761                 case Q3DEFORM_WAVE:
11762                         // deform vertex array to make wavey water and flags and such
11763                         waveparms[0] = deform->waveparms[0];
11764                         waveparms[1] = deform->waveparms[1];
11765                         waveparms[2] = deform->waveparms[2];
11766                         waveparms[3] = deform->waveparms[3];
11767                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11768                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11769                         // this is how a divisor of vertex influence on deformation
11770                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11771                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11772                         for (j = 0;j < rsurface.batchnumvertices;j++)
11773                         {
11774                                 // if the wavefunc depends on time, evaluate it per-vertex
11775                                 if (waveparms[3])
11776                                 {
11777                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11778                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11779                                 }
11780                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11781                         }
11782                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11783                         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);
11784                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11785                         rsurface.batchvertex3f_vertexbuffer = NULL;
11786                         rsurface.batchvertex3f_bufferoffset = 0;
11787                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11788                         rsurface.batchsvector3f_vertexbuffer = NULL;
11789                         rsurface.batchsvector3f_bufferoffset = 0;
11790                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11791                         rsurface.batchtvector3f_vertexbuffer = NULL;
11792                         rsurface.batchtvector3f_bufferoffset = 0;
11793                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11794                         rsurface.batchnormal3f_vertexbuffer = NULL;
11795                         rsurface.batchnormal3f_bufferoffset = 0;
11796                         break;
11797                 case Q3DEFORM_BULGE:
11798                         // deform vertex array to make the surface have moving bulges
11799                         for (j = 0;j < rsurface.batchnumvertices;j++)
11800                         {
11801                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11802                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11803                         }
11804                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11805                         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);
11806                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11807                         rsurface.batchvertex3f_vertexbuffer = NULL;
11808                         rsurface.batchvertex3f_bufferoffset = 0;
11809                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11810                         rsurface.batchsvector3f_vertexbuffer = NULL;
11811                         rsurface.batchsvector3f_bufferoffset = 0;
11812                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11813                         rsurface.batchtvector3f_vertexbuffer = NULL;
11814                         rsurface.batchtvector3f_bufferoffset = 0;
11815                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11816                         rsurface.batchnormal3f_vertexbuffer = NULL;
11817                         rsurface.batchnormal3f_bufferoffset = 0;
11818                         break;
11819                 case Q3DEFORM_MOVE:
11820                         // deform vertex array
11821                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11822                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11823                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11824                         VectorScale(deform->parms, scale, waveparms);
11825                         for (j = 0;j < rsurface.batchnumvertices;j++)
11826                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11827                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11828                         rsurface.batchvertex3f_vertexbuffer = NULL;
11829                         rsurface.batchvertex3f_bufferoffset = 0;
11830                         break;
11831                 }
11832         }
11833
11834         // generate texcoords based on the chosen texcoord source
11835         switch(rsurface.texture->tcgen.tcgen)
11836         {
11837         default:
11838         case Q3TCGEN_TEXTURE:
11839                 break;
11840         case Q3TCGEN_LIGHTMAP:
11841                 if (rsurface.batchtexcoordlightmap2f)
11842                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11843                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11844                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11845                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11846                 break;
11847         case Q3TCGEN_VECTOR:
11848                 for (j = 0;j < rsurface.batchnumvertices;j++)
11849                 {
11850                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11851                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11852                 }
11853                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11854                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11855                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11856                 break;
11857         case Q3TCGEN_ENVIRONMENT:
11858                 // make environment reflections using a spheremap
11859                 for (j = 0;j < rsurface.batchnumvertices;j++)
11860                 {
11861                         // identical to Q3A's method, but executed in worldspace so
11862                         // carried models can be shiny too
11863
11864                         float viewer[3], d, reflected[3], worldreflected[3];
11865
11866                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11867                         // VectorNormalize(viewer);
11868
11869                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11870
11871                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11872                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11873                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11874                         // note: this is proportinal to viewer, so we can normalize later
11875
11876                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11877                         VectorNormalize(worldreflected);
11878
11879                         // note: this sphere map only uses world x and z!
11880                         // so positive and negative y will LOOK THE SAME.
11881                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11882                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11883                 }
11884                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11885                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11886                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11887                 break;
11888         }
11889         // the only tcmod that needs software vertex processing is turbulent, so
11890         // check for it here and apply the changes if needed
11891         // and we only support that as the first one
11892         // (handling a mixture of turbulent and other tcmods would be problematic
11893         //  without punting it entirely to a software path)
11894         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11895         {
11896                 amplitude = rsurface.texture->tcmods[0].parms[1];
11897                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11898                 for (j = 0;j < rsurface.batchnumvertices;j++)
11899                 {
11900                         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);
11901                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11902                 }
11903                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11904                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11905                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11906         }
11907
11908         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11909         {
11910                 // convert the modified arrays to vertex structs
11911                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11912                 rsurface.batchvertexmeshbuffer = NULL;
11913                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11914                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11915                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11916                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11917                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11918                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11919                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11920                 {
11921                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11922                         {
11923                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11924                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11925                         }
11926                 }
11927                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11928                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11929                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11930                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11931                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11932                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11933                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11934                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11935                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11936         }
11937
11938         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11939         {
11940                 // convert the modified arrays to vertex structs
11941                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11942                 rsurface.batchvertexpositionbuffer = NULL;
11943                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11944                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11945                 else
11946                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11947                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11948         }
11949 }
11950
11951 void RSurf_DrawBatch(void)
11952 {
11953         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);
11954 }
11955
11956 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11957 {
11958         // pick the closest matching water plane
11959         int planeindex, vertexindex, bestplaneindex = -1;
11960         float d, bestd;
11961         vec3_t vert;
11962         const float *v;
11963         r_waterstate_waterplane_t *p;
11964         bestd = 0;
11965         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11966         {
11967                 if(p->camera_entity != rsurface.texture->camera_entity)
11968                         continue;
11969                 d = 0;
11970                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11971                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11972                 {
11973                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11974                         d += fabs(PlaneDiff(vert, &p->plane));
11975                 }
11976                 if (bestd > d || bestplaneindex < 0)
11977                 {
11978                         bestd = d;
11979                         bestplaneindex = planeindex;
11980                 }
11981         }
11982         return bestplaneindex;
11983 }
11984
11985 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11986 {
11987         int i;
11988         for (i = 0;i < rsurface.batchnumvertices;i++)
11989                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11990         rsurface.passcolor4f = rsurface.array_passcolor4f;
11991         rsurface.passcolor4f_vertexbuffer = 0;
11992         rsurface.passcolor4f_bufferoffset = 0;
11993 }
11994
11995 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11996 {
11997         int i;
11998         float f;
11999         const float *v;
12000         const float *c;
12001         float *c2;
12002         if (rsurface.passcolor4f)
12003         {
12004                 // generate color arrays
12005                 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)
12006                 {
12007                         f = RSurf_FogVertex(v);
12008                         c2[0] = c[0] * f;
12009                         c2[1] = c[1] * f;
12010                         c2[2] = c[2] * f;
12011                         c2[3] = c[3];
12012                 }
12013         }
12014         else
12015         {
12016                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12017                 {
12018                         f = RSurf_FogVertex(v);
12019                         c2[0] = f;
12020                         c2[1] = f;
12021                         c2[2] = f;
12022                         c2[3] = 1;
12023                 }
12024         }
12025         rsurface.passcolor4f = rsurface.array_passcolor4f;
12026         rsurface.passcolor4f_vertexbuffer = 0;
12027         rsurface.passcolor4f_bufferoffset = 0;
12028 }
12029
12030 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12031 {
12032         int i;
12033         float f;
12034         const float *v;
12035         const float *c;
12036         float *c2;
12037         if (!rsurface.passcolor4f)
12038                 return;
12039         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)
12040         {
12041                 f = RSurf_FogVertex(v);
12042                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12043                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12044                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12045                 c2[3] = c[3];
12046         }
12047         rsurface.passcolor4f = rsurface.array_passcolor4f;
12048         rsurface.passcolor4f_vertexbuffer = 0;
12049         rsurface.passcolor4f_bufferoffset = 0;
12050 }
12051
12052 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12053 {
12054         int i;
12055         const float *c;
12056         float *c2;
12057         if (!rsurface.passcolor4f)
12058                 return;
12059         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12060         {
12061                 c2[0] = c[0] * r;
12062                 c2[1] = c[1] * g;
12063                 c2[2] = c[2] * b;
12064                 c2[3] = c[3] * a;
12065         }
12066         rsurface.passcolor4f = rsurface.array_passcolor4f;
12067         rsurface.passcolor4f_vertexbuffer = 0;
12068         rsurface.passcolor4f_bufferoffset = 0;
12069 }
12070
12071 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12072 {
12073         int i;
12074         const float *c;
12075         float *c2;
12076         if (!rsurface.passcolor4f)
12077                 return;
12078         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12079         {
12080                 c2[0] = c[0] + r_refdef.scene.ambient;
12081                 c2[1] = c[1] + r_refdef.scene.ambient;
12082                 c2[2] = c[2] + r_refdef.scene.ambient;
12083                 c2[3] = c[3];
12084         }
12085         rsurface.passcolor4f = rsurface.array_passcolor4f;
12086         rsurface.passcolor4f_vertexbuffer = 0;
12087         rsurface.passcolor4f_bufferoffset = 0;
12088 }
12089
12090 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12091 {
12092         // TODO: optimize
12093         rsurface.passcolor4f = NULL;
12094         rsurface.passcolor4f_vertexbuffer = 0;
12095         rsurface.passcolor4f_bufferoffset = 0;
12096         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12097         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12098         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12099         GL_Color(r, g, b, a);
12100         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12101         RSurf_DrawBatch();
12102 }
12103
12104 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12105 {
12106         // TODO: optimize applyfog && applycolor case
12107         // just apply fog if necessary, and tint the fog color array if necessary
12108         rsurface.passcolor4f = NULL;
12109         rsurface.passcolor4f_vertexbuffer = 0;
12110         rsurface.passcolor4f_bufferoffset = 0;
12111         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12112         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12113         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12114         GL_Color(r, g, b, a);
12115         RSurf_DrawBatch();
12116 }
12117
12118 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12119 {
12120         // TODO: optimize
12121         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12122         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12123         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12124         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12125         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12126         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12127         GL_Color(r, g, b, a);
12128         RSurf_DrawBatch();
12129 }
12130
12131 static void RSurf_DrawBatch_GL11_ClampColor(void)
12132 {
12133         int i;
12134         const float *c1;
12135         float *c2;
12136         if (!rsurface.passcolor4f)
12137                 return;
12138         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12139         {
12140                 c2[0] = bound(0.0f, c1[0], 1.0f);
12141                 c2[1] = bound(0.0f, c1[1], 1.0f);
12142                 c2[2] = bound(0.0f, c1[2], 1.0f);
12143                 c2[3] = bound(0.0f, c1[3], 1.0f);
12144         }
12145 }
12146
12147 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12148 {
12149         int i;
12150         float f;
12151         float alpha;
12152         const float *v;
12153         const float *n;
12154         float *c;
12155         vec3_t ambientcolor;
12156         vec3_t diffusecolor;
12157         vec3_t lightdir;
12158         // TODO: optimize
12159         // model lighting
12160         VectorCopy(rsurface.modellight_lightdir, lightdir);
12161         f = 0.5f * r_refdef.lightmapintensity;
12162         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12163         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12164         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12165         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12166         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12167         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12168         alpha = *a;
12169         if (VectorLength2(diffusecolor) > 0)
12170         {
12171                 // q3-style directional shading
12172                 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)
12173                 {
12174                         if ((f = DotProduct(n, lightdir)) > 0)
12175                                 VectorMA(ambientcolor, f, diffusecolor, c);
12176                         else
12177                                 VectorCopy(ambientcolor, c);
12178                         c[3] = alpha;
12179                 }
12180                 *r = 1;
12181                 *g = 1;
12182                 *b = 1;
12183                 *a = 1;
12184                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12185                 rsurface.passcolor4f_vertexbuffer = 0;
12186                 rsurface.passcolor4f_bufferoffset = 0;
12187                 *applycolor = false;
12188         }
12189         else
12190         {
12191                 *r = ambientcolor[0];
12192                 *g = ambientcolor[1];
12193                 *b = ambientcolor[2];
12194                 rsurface.passcolor4f = NULL;
12195                 rsurface.passcolor4f_vertexbuffer = 0;
12196                 rsurface.passcolor4f_bufferoffset = 0;
12197         }
12198 }
12199
12200 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12201 {
12202         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12203         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12204         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12205         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12206         GL_Color(r, g, b, a);
12207         RSurf_DrawBatch();
12208 }
12209
12210 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12211 {
12212         int i;
12213         float f;
12214         const float *v;
12215         float *c;
12216         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12217         {
12218                 f = 1 - RSurf_FogVertex(v);
12219                 c[0] = r;
12220                 c[1] = g;
12221                 c[2] = b;
12222                 c[3] = f * a;
12223         }
12224 }
12225
12226 void RSurf_SetupDepthAndCulling(void)
12227 {
12228         // submodels are biased to avoid z-fighting with world surfaces that they
12229         // may be exactly overlapping (avoids z-fighting artifacts on certain
12230         // doors and things in Quake maps)
12231         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12232         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12233         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12234         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12235 }
12236
12237 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12238 {
12239         // transparent sky would be ridiculous
12240         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12241                 return;
12242         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12243         skyrenderlater = true;
12244         RSurf_SetupDepthAndCulling();
12245         GL_DepthMask(true);
12246         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12247         // skymasking on them, and Quake3 never did sky masking (unlike
12248         // software Quake and software Quake2), so disable the sky masking
12249         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12250         // and skymasking also looks very bad when noclipping outside the
12251         // level, so don't use it then either.
12252         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12253         {
12254                 R_Mesh_ResetTextureState();
12255                 if (skyrendermasked)
12256                 {
12257                         R_SetupShader_DepthOrShadow();
12258                         // depth-only (masking)
12259                         GL_ColorMask(0,0,0,0);
12260                         // just to make sure that braindead drivers don't draw
12261                         // anything despite that colormask...
12262                         GL_BlendFunc(GL_ZERO, GL_ONE);
12263                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12264                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12265                 }
12266                 else
12267                 {
12268                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12269                         // fog sky
12270                         GL_BlendFunc(GL_ONE, GL_ZERO);
12271                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12272                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12273                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12274                 }
12275                 RSurf_DrawBatch();
12276                 if (skyrendermasked)
12277                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12278         }
12279         R_Mesh_ResetTextureState();
12280         GL_Color(1, 1, 1, 1);
12281 }
12282
12283 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12284 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12285 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12286 {
12287         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12288                 return;
12289         if (prepass)
12290         {
12291                 // render screenspace normalmap to texture
12292                 GL_DepthMask(true);
12293                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12294                 RSurf_DrawBatch();
12295                 return;
12296         }
12297
12298         // bind lightmap texture
12299
12300         // water/refraction/reflection/camera surfaces have to be handled specially
12301         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12302         {
12303                 int start, end, startplaneindex;
12304                 for (start = 0;start < texturenumsurfaces;start = end)
12305                 {
12306                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12307                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12308                                 ;
12309                         // now that we have a batch using the same planeindex, render it
12310                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12311                         {
12312                                 // render water or distortion background
12313                                 GL_DepthMask(true);
12314                                 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));
12315                                 RSurf_DrawBatch();
12316                                 // blend surface on top
12317                                 GL_DepthMask(false);
12318                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12319                                 RSurf_DrawBatch();
12320                         }
12321                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12322                         {
12323                                 // render surface with reflection texture as input
12324                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12325                                 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));
12326                                 RSurf_DrawBatch();
12327                         }
12328                 }
12329                 return;
12330         }
12331
12332         // render surface batch normally
12333         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12334         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12335         RSurf_DrawBatch();
12336 }
12337
12338 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12339 {
12340         // OpenGL 1.3 path - anything not completely ancient
12341         qboolean applycolor;
12342         qboolean applyfog;
12343         int layerindex;
12344         const texturelayer_t *layer;
12345         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);
12346         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12347
12348         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12349         {
12350                 vec4_t layercolor;
12351                 int layertexrgbscale;
12352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12353                 {
12354                         if (layerindex == 0)
12355                                 GL_AlphaTest(true);
12356                         else
12357                         {
12358                                 GL_AlphaTest(false);
12359                                 GL_DepthFunc(GL_EQUAL);
12360                         }
12361                 }
12362                 GL_DepthMask(layer->depthmask && writedepth);
12363                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12364                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12365                 {
12366                         layertexrgbscale = 4;
12367                         VectorScale(layer->color, 0.25f, layercolor);
12368                 }
12369                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12370                 {
12371                         layertexrgbscale = 2;
12372                         VectorScale(layer->color, 0.5f, layercolor);
12373                 }
12374                 else
12375                 {
12376                         layertexrgbscale = 1;
12377                         VectorScale(layer->color, 1.0f, layercolor);
12378                 }
12379                 layercolor[3] = layer->color[3];
12380                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12381                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12382                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12383                 switch (layer->type)
12384                 {
12385                 case TEXTURELAYERTYPE_LITTEXTURE:
12386                         // single-pass lightmapped texture with 2x rgbscale
12387                         R_Mesh_TexBind(0, r_texture_white);
12388                         R_Mesh_TexMatrix(0, NULL);
12389                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12390                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12391                         R_Mesh_TexBind(1, layer->texture);
12392                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12393                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12394                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12395                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12396                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12397                         else if (rsurface.uselightmaptexture)
12398                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12399                         else
12400                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12401                         break;
12402                 case TEXTURELAYERTYPE_TEXTURE:
12403                         // singletexture unlit texture with transparency support
12404                         R_Mesh_TexBind(0, layer->texture);
12405                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12406                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12407                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12408                         R_Mesh_TexBind(1, 0);
12409                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12410                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12411                         break;
12412                 case TEXTURELAYERTYPE_FOG:
12413                         // singletexture fogging
12414                         if (layer->texture)
12415                         {
12416                                 R_Mesh_TexBind(0, layer->texture);
12417                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12418                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12419                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12420                         }
12421                         else
12422                         {
12423                                 R_Mesh_TexBind(0, 0);
12424                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12425                         }
12426                         R_Mesh_TexBind(1, 0);
12427                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12428                         // generate a color array for the fog pass
12429                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12430                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12431                         RSurf_DrawBatch();
12432                         break;
12433                 default:
12434                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12435                 }
12436         }
12437         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12438         {
12439                 GL_DepthFunc(GL_LEQUAL);
12440                 GL_AlphaTest(false);
12441         }
12442 }
12443
12444 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12445 {
12446         // OpenGL 1.1 - crusty old voodoo path
12447         qboolean applyfog;
12448         int layerindex;
12449         const texturelayer_t *layer;
12450         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);
12451         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12452
12453         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12454         {
12455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12456                 {
12457                         if (layerindex == 0)
12458                                 GL_AlphaTest(true);
12459                         else
12460                         {
12461                                 GL_AlphaTest(false);
12462                                 GL_DepthFunc(GL_EQUAL);
12463                         }
12464                 }
12465                 GL_DepthMask(layer->depthmask && writedepth);
12466                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12467                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12468                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12469                 switch (layer->type)
12470                 {
12471                 case TEXTURELAYERTYPE_LITTEXTURE:
12472                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12473                         {
12474                                 // two-pass lit texture with 2x rgbscale
12475                                 // first the lightmap pass
12476                                 R_Mesh_TexBind(0, r_texture_white);
12477                                 R_Mesh_TexMatrix(0, NULL);
12478                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12479                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12480                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12481                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12482                                 else if (rsurface.uselightmaptexture)
12483                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12484                                 else
12485                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12486                                 // then apply the texture to it
12487                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12488                                 R_Mesh_TexBind(0, layer->texture);
12489                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12490                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12491                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12492                                 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);
12493                         }
12494                         else
12495                         {
12496                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12497                                 R_Mesh_TexBind(0, layer->texture);
12498                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12499                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12500                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12501                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12502                                         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);
12503                                 else
12504                                         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);
12505                         }
12506                         break;
12507                 case TEXTURELAYERTYPE_TEXTURE:
12508                         // singletexture unlit texture with transparency support
12509                         R_Mesh_TexBind(0, layer->texture);
12510                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12511                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12512                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12513                         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);
12514                         break;
12515                 case TEXTURELAYERTYPE_FOG:
12516                         // singletexture fogging
12517                         if (layer->texture)
12518                         {
12519                                 R_Mesh_TexBind(0, layer->texture);
12520                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12521                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12522                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12523                         }
12524                         else
12525                         {
12526                                 R_Mesh_TexBind(0, 0);
12527                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12528                         }
12529                         // generate a color array for the fog pass
12530                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12531                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12532                         RSurf_DrawBatch();
12533                         break;
12534                 default:
12535                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12536                 }
12537         }
12538         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12539         {
12540                 GL_DepthFunc(GL_LEQUAL);
12541                 GL_AlphaTest(false);
12542         }
12543 }
12544
12545 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12546 {
12547         int vi;
12548         int j;
12549         r_vertexgeneric_t *batchvertex;
12550         float c[4];
12551
12552         GL_AlphaTest(false);
12553         R_Mesh_ResetTextureState();
12554         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12555
12556         if(rsurface.texture && rsurface.texture->currentskinframe)
12557         {
12558                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12559                 c[3] *= rsurface.texture->currentalpha;
12560         }
12561         else
12562         {
12563                 c[0] = 1;
12564                 c[1] = 0;
12565                 c[2] = 1;
12566                 c[3] = 1;
12567         }
12568
12569         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12570         {
12571                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12572                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12573                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12574         }
12575
12576         // brighten it up (as texture value 127 means "unlit")
12577         c[0] *= 2 * r_refdef.view.colorscale;
12578         c[1] *= 2 * r_refdef.view.colorscale;
12579         c[2] *= 2 * r_refdef.view.colorscale;
12580
12581         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12582                 c[3] *= r_wateralpha.value;
12583
12584         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12585         {
12586                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12587                 GL_DepthMask(false);
12588         }
12589         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12590         {
12591                 GL_BlendFunc(GL_ONE, GL_ONE);
12592                 GL_DepthMask(false);
12593         }
12594         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12595         {
12596                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12597                 GL_DepthMask(false);
12598         }
12599         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12600         {
12601                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12602                 GL_DepthMask(false);
12603         }
12604         else
12605         {
12606                 GL_BlendFunc(GL_ONE, GL_ZERO);
12607                 GL_DepthMask(writedepth);
12608         }
12609
12610         if (r_showsurfaces.integer == 3)
12611         {
12612                 rsurface.passcolor4f = NULL;
12613
12614                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12615                 {
12616                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12617
12618                         rsurface.passcolor4f = NULL;
12619                         rsurface.passcolor4f_vertexbuffer = 0;
12620                         rsurface.passcolor4f_bufferoffset = 0;
12621                 }
12622                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12623                 {
12624                         qboolean applycolor = true;
12625                         float one = 1.0;
12626
12627                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12628
12629                         r_refdef.lightmapintensity = 1;
12630                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12631                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12632                 }
12633                 else
12634                 {
12635                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12636
12637                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12638                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12639                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12640                 }
12641
12642                 if(!rsurface.passcolor4f)
12643                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12644
12645                 RSurf_DrawBatch_GL11_ApplyAmbient();
12646                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12647                 if(r_refdef.fogenabled)
12648                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12649                 RSurf_DrawBatch_GL11_ClampColor();
12650
12651                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12652                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12653                 RSurf_DrawBatch();
12654         }
12655         else if (!r_refdef.view.showdebug)
12656         {
12657                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12658                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12659                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12660                 {
12661                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12662                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12663                 }
12664                 R_Mesh_PrepareVertices_Generic_Unlock();
12665                 RSurf_DrawBatch();
12666         }
12667         else if (r_showsurfaces.integer == 4)
12668         {
12669                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12670                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12671                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12672                 {
12673                         unsigned char c = vi << 3;
12674                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12675                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12676                 }
12677                 R_Mesh_PrepareVertices_Generic_Unlock();
12678                 RSurf_DrawBatch();
12679         }
12680         else if (r_showsurfaces.integer == 2)
12681         {
12682                 const int *e;
12683                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12684                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12685                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12686                 {
12687                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12688                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12689                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12690                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12691                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12692                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12693                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12694                 }
12695                 R_Mesh_PrepareVertices_Generic_Unlock();
12696                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12697         }
12698         else
12699         {
12700                 int texturesurfaceindex;
12701                 int k;
12702                 const msurface_t *surface;
12703                 unsigned char surfacecolor4ub[4];
12704                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12705                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12706                 vi = 0;
12707                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12708                 {
12709                         surface = texturesurfacelist[texturesurfaceindex];
12710                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12711                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12712                         for (j = 0;j < surface->num_vertices;j++)
12713                         {
12714                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12715                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12716                                 vi++;
12717                         }
12718                 }
12719                 R_Mesh_PrepareVertices_Generic_Unlock();
12720                 RSurf_DrawBatch();
12721         }
12722 }
12723
12724 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12725 {
12726         CHECKGLERROR
12727         RSurf_SetupDepthAndCulling();
12728         if (r_showsurfaces.integer)
12729         {
12730                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12731                 return;
12732         }
12733         switch (vid.renderpath)
12734         {
12735         case RENDERPATH_GL20:
12736         case RENDERPATH_CGGL:
12737         case RENDERPATH_D3D9:
12738         case RENDERPATH_D3D10:
12739         case RENDERPATH_D3D11:
12740                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12741                 break;
12742         case RENDERPATH_GL13:
12743                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12744                 break;
12745         case RENDERPATH_GL11:
12746                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12747                 break;
12748         }
12749         CHECKGLERROR
12750 }
12751
12752 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12753 {
12754         CHECKGLERROR
12755         RSurf_SetupDepthAndCulling();
12756         if (r_showsurfaces.integer)
12757         {
12758                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12759                 return;
12760         }
12761         switch (vid.renderpath)
12762         {
12763         case RENDERPATH_GL20:
12764         case RENDERPATH_CGGL:
12765         case RENDERPATH_D3D9:
12766         case RENDERPATH_D3D10:
12767         case RENDERPATH_D3D11:
12768                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12769                 break;
12770         case RENDERPATH_GL13:
12771                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12772                 break;
12773         case RENDERPATH_GL11:
12774                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12775                 break;
12776         }
12777         CHECKGLERROR
12778 }
12779
12780 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12781 {
12782         int i, j;
12783         int texturenumsurfaces, endsurface;
12784         texture_t *texture;
12785         const msurface_t *surface;
12786 #define MAXBATCH_TRANSPARENTSURFACES 256
12787         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12788
12789         // if the model is static it doesn't matter what value we give for
12790         // wantnormals and wanttangents, so this logic uses only rules applicable
12791         // to a model, knowing that they are meaningless otherwise
12792         if (ent == r_refdef.scene.worldentity)
12793                 RSurf_ActiveWorldEntity();
12794         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12795                 RSurf_ActiveModelEntity(ent, false, false, false);
12796         else
12797         {
12798                 switch (vid.renderpath)
12799                 {
12800                 case RENDERPATH_GL20:
12801                 case RENDERPATH_CGGL:
12802                 case RENDERPATH_D3D9:
12803                 case RENDERPATH_D3D10:
12804                 case RENDERPATH_D3D11:
12805                         RSurf_ActiveModelEntity(ent, true, true, false);
12806                         break;
12807                 case RENDERPATH_GL13:
12808                 case RENDERPATH_GL11:
12809                         RSurf_ActiveModelEntity(ent, true, false, false);
12810                         break;
12811                 }
12812         }
12813
12814         if (r_transparentdepthmasking.integer)
12815         {
12816                 qboolean setup = false;
12817                 for (i = 0;i < numsurfaces;i = j)
12818                 {
12819                         j = i + 1;
12820                         surface = rsurface.modelsurfaces + surfacelist[i];
12821                         texture = surface->texture;
12822                         rsurface.texture = R_GetCurrentTexture(texture);
12823                         rsurface.lightmaptexture = NULL;
12824                         rsurface.deluxemaptexture = NULL;
12825                         rsurface.uselightmaptexture = false;
12826                         // scan ahead until we find a different texture
12827                         endsurface = min(i + 1024, numsurfaces);
12828                         texturenumsurfaces = 0;
12829                         texturesurfacelist[texturenumsurfaces++] = surface;
12830                         for (;j < endsurface;j++)
12831                         {
12832                                 surface = rsurface.modelsurfaces + surfacelist[j];
12833                                 if (texture != surface->texture)
12834                                         break;
12835                                 texturesurfacelist[texturenumsurfaces++] = surface;
12836                         }
12837                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12838                                 continue;
12839                         // render the range of surfaces as depth
12840                         if (!setup)
12841                         {
12842                                 setup = true;
12843                                 GL_ColorMask(0,0,0,0);
12844                                 GL_Color(1,1,1,1);
12845                                 GL_DepthTest(true);
12846                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12847                                 GL_DepthMask(true);
12848                                 GL_AlphaTest(false);
12849                                 R_Mesh_ResetTextureState();
12850                                 R_SetupShader_DepthOrShadow();
12851                         }
12852                         RSurf_SetupDepthAndCulling();
12853                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12854                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12855                         RSurf_DrawBatch();
12856                 }
12857                 if (setup)
12858                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12859         }
12860
12861         for (i = 0;i < numsurfaces;i = j)
12862         {
12863                 j = i + 1;
12864                 surface = rsurface.modelsurfaces + surfacelist[i];
12865                 texture = surface->texture;
12866                 rsurface.texture = R_GetCurrentTexture(texture);
12867                 rsurface.lightmaptexture = surface->lightmaptexture;
12868                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12869                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12870                 // scan ahead until we find a different texture
12871                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12872                 texturenumsurfaces = 0;
12873                 texturesurfacelist[texturenumsurfaces++] = surface;
12874                 for (;j < endsurface;j++)
12875                 {
12876                         surface = rsurface.modelsurfaces + surfacelist[j];
12877                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12878                                 break;
12879                         texturesurfacelist[texturenumsurfaces++] = surface;
12880                 }
12881                 // render the range of surfaces
12882                 if (ent == r_refdef.scene.worldentity)
12883                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12884                 else
12885                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12886         }
12887         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12888         GL_AlphaTest(false);
12889 }
12890
12891 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12892 {
12893         // transparent surfaces get pushed off into the transparent queue
12894         int surfacelistindex;
12895         const msurface_t *surface;
12896         vec3_t tempcenter, center;
12897         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12898         {
12899                 surface = texturesurfacelist[surfacelistindex];
12900                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12901                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12902                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12903                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12904                 if (queueentity->transparent_offset) // transparent offset
12905                 {
12906                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12907                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12908                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12909                 }
12910                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12911         }
12912 }
12913
12914 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12915 {
12916         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12917                 return;
12918         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12919                 return;
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
12926 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12927 {
12928         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12929         CHECKGLERROR
12930         if (depthonly)
12931                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12932         else if (prepass)
12933         {
12934                 if (!rsurface.texture->currentnumlayers)
12935                         return;
12936                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12937                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12938                 else
12939                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12940         }
12941         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12942                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12943         else if (!rsurface.texture->currentnumlayers)
12944                 return;
12945         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12946         {
12947                 // in the deferred case, transparent surfaces were queued during prepass
12948                 if (!r_shadow_usingdeferredprepass)
12949                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12950         }
12951         else
12952         {
12953                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12954                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12955         }
12956         CHECKGLERROR
12957 }
12958
12959 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12960 {
12961         int i, j;
12962         texture_t *texture;
12963         // break the surface list down into batches by texture and use of lightmapping
12964         for (i = 0;i < numsurfaces;i = j)
12965         {
12966                 j = i + 1;
12967                 // texture is the base texture pointer, rsurface.texture is the
12968                 // current frame/skin the texture is directing us to use (for example
12969                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12970                 // use skin 1 instead)
12971                 texture = surfacelist[i]->texture;
12972                 rsurface.texture = R_GetCurrentTexture(texture);
12973                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12974                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12975                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12976                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12977                 {
12978                         // if this texture is not the kind we want, skip ahead to the next one
12979                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12980                                 ;
12981                         continue;
12982                 }
12983                 // simply scan ahead until we find a different texture or lightmap state
12984                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12985                         ;
12986                 // render the range of surfaces
12987                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12988         }
12989 }
12990
12991 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12992 {
12993         CHECKGLERROR
12994         if (depthonly)
12995                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12996         else if (prepass)
12997         {
12998                 if (!rsurface.texture->currentnumlayers)
12999                         return;
13000                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13001                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13002                 else
13003                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13004         }
13005         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13006                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13007         else if (!rsurface.texture->currentnumlayers)
13008                 return;
13009         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13010         {
13011                 // in the deferred case, transparent surfaces were queued during prepass
13012                 if (!r_shadow_usingdeferredprepass)
13013                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13014         }
13015         else
13016         {
13017                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13018                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13019         }
13020         CHECKGLERROR
13021 }
13022
13023 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13024 {
13025         int i, j;
13026         texture_t *texture;
13027         // break the surface list down into batches by texture and use of lightmapping
13028         for (i = 0;i < numsurfaces;i = j)
13029         {
13030                 j = i + 1;
13031                 // texture is the base texture pointer, rsurface.texture is the
13032                 // current frame/skin the texture is directing us to use (for example
13033                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13034                 // use skin 1 instead)
13035                 texture = surfacelist[i]->texture;
13036                 rsurface.texture = R_GetCurrentTexture(texture);
13037                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13038                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13039                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13040                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13041                 {
13042                         // if this texture is not the kind we want, skip ahead to the next one
13043                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13044                                 ;
13045                         continue;
13046                 }
13047                 // simply scan ahead until we find a different texture or lightmap state
13048                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13049                         ;
13050                 // render the range of surfaces
13051                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13052         }
13053 }
13054
13055 float locboxvertex3f[6*4*3] =
13056 {
13057         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13058         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13059         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13060         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13061         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13062         1,0,0, 0,0,0, 0,1,0, 1,1,0
13063 };
13064
13065 unsigned short locboxelements[6*2*3] =
13066 {
13067          0, 1, 2, 0, 2, 3,
13068          4, 5, 6, 4, 6, 7,
13069          8, 9,10, 8,10,11,
13070         12,13,14, 12,14,15,
13071         16,17,18, 16,18,19,
13072         20,21,22, 20,22,23
13073 };
13074
13075 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13076 {
13077         int i, j;
13078         cl_locnode_t *loc = (cl_locnode_t *)ent;
13079         vec3_t mins, size;
13080         float vertex3f[6*4*3];
13081         CHECKGLERROR
13082         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13083         GL_DepthMask(false);
13084         GL_DepthRange(0, 1);
13085         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13086         GL_DepthTest(true);
13087         GL_CullFace(GL_NONE);
13088         R_EntityMatrix(&identitymatrix);
13089
13090         R_Mesh_ResetTextureState();
13091
13092         i = surfacelist[0];
13093         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13094                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13095                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13096                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13097
13098         if (VectorCompare(loc->mins, loc->maxs))
13099         {
13100                 VectorSet(size, 2, 2, 2);
13101                 VectorMA(loc->mins, -0.5f, size, mins);
13102         }
13103         else
13104         {
13105                 VectorCopy(loc->mins, mins);
13106                 VectorSubtract(loc->maxs, loc->mins, size);
13107         }
13108
13109         for (i = 0;i < 6*4*3;)
13110                 for (j = 0;j < 3;j++, i++)
13111                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13112
13113         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13114         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13115         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13116 }
13117
13118 void R_DrawLocs(void)
13119 {
13120         int index;
13121         cl_locnode_t *loc, *nearestloc;
13122         vec3_t center;
13123         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13124         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13125         {
13126                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13127                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13128         }
13129 }
13130
13131 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13132 {
13133         if (decalsystem->decals)
13134                 Mem_Free(decalsystem->decals);
13135         memset(decalsystem, 0, sizeof(*decalsystem));
13136 }
13137
13138 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)
13139 {
13140         tridecal_t *decal;
13141         tridecal_t *decals;
13142         int i;
13143
13144         // expand or initialize the system
13145         if (decalsystem->maxdecals <= decalsystem->numdecals)
13146         {
13147                 decalsystem_t old = *decalsystem;
13148                 qboolean useshortelements;
13149                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13150                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13151                 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)));
13152                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13153                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13154                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13155                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13156                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13157                 if (decalsystem->numdecals)
13158                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13159                 if (old.decals)
13160                         Mem_Free(old.decals);
13161                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13162                         decalsystem->element3i[i] = i;
13163                 if (useshortelements)
13164                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13165                                 decalsystem->element3s[i] = i;
13166         }
13167
13168         // grab a decal and search for another free slot for the next one
13169         decals = decalsystem->decals;
13170         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13171         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13172                 ;
13173         decalsystem->freedecal = i;
13174         if (decalsystem->numdecals <= i)
13175                 decalsystem->numdecals = i + 1;
13176
13177         // initialize the decal
13178         decal->lived = 0;
13179         decal->triangleindex = triangleindex;
13180         decal->surfaceindex = surfaceindex;
13181         decal->decalsequence = decalsequence;
13182         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13183         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13184         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13185         decal->color4ub[0][3] = 255;
13186         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13187         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13188         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13189         decal->color4ub[1][3] = 255;
13190         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13191         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13192         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13193         decal->color4ub[2][3] = 255;
13194         decal->vertex3f[0][0] = v0[0];
13195         decal->vertex3f[0][1] = v0[1];
13196         decal->vertex3f[0][2] = v0[2];
13197         decal->vertex3f[1][0] = v1[0];
13198         decal->vertex3f[1][1] = v1[1];
13199         decal->vertex3f[1][2] = v1[2];
13200         decal->vertex3f[2][0] = v2[0];
13201         decal->vertex3f[2][1] = v2[1];
13202         decal->vertex3f[2][2] = v2[2];
13203         decal->texcoord2f[0][0] = t0[0];
13204         decal->texcoord2f[0][1] = t0[1];
13205         decal->texcoord2f[1][0] = t1[0];
13206         decal->texcoord2f[1][1] = t1[1];
13207         decal->texcoord2f[2][0] = t2[0];
13208         decal->texcoord2f[2][1] = t2[1];
13209 }
13210
13211 extern cvar_t cl_decals_bias;
13212 extern cvar_t cl_decals_models;
13213 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13214 // baseparms, parms, temps
13215 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)
13216 {
13217         int cornerindex;
13218         int index;
13219         float v[9][3];
13220         const float *vertex3f;
13221         int numpoints;
13222         float points[2][9][3];
13223         float temp[3];
13224         float tc[9][2];
13225         float f;
13226         float c[9][4];
13227         const int *e;
13228
13229         e = rsurface.modelelement3i + 3*triangleindex;
13230
13231         vertex3f = rsurface.modelvertex3f;
13232
13233         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13234         {
13235                 index = 3*e[cornerindex];
13236                 VectorCopy(vertex3f + index, v[cornerindex]);
13237         }
13238         // cull backfaces
13239         //TriangleNormal(v[0], v[1], v[2], normal);
13240         //if (DotProduct(normal, localnormal) < 0.0f)
13241         //      continue;
13242         // clip by each of the box planes formed from the projection matrix
13243         // if anything survives, we emit the decal
13244         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]);
13245         if (numpoints < 3)
13246                 return;
13247         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]);
13248         if (numpoints < 3)
13249                 return;
13250         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]);
13251         if (numpoints < 3)
13252                 return;
13253         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]);
13254         if (numpoints < 3)
13255                 return;
13256         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]);
13257         if (numpoints < 3)
13258                 return;
13259         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]);
13260         if (numpoints < 3)
13261                 return;
13262         // some part of the triangle survived, so we have to accept it...
13263         if (dynamic)
13264         {
13265                 // dynamic always uses the original triangle
13266                 numpoints = 3;
13267                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13268                 {
13269                         index = 3*e[cornerindex];
13270                         VectorCopy(vertex3f + index, v[cornerindex]);
13271                 }
13272         }
13273         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13274         {
13275                 // convert vertex positions to texcoords
13276                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13277                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13278                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13279                 // calculate distance fade from the projection origin
13280                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13281                 f = bound(0.0f, f, 1.0f);
13282                 c[cornerindex][0] = r * f;
13283                 c[cornerindex][1] = g * f;
13284                 c[cornerindex][2] = b * f;
13285                 c[cornerindex][3] = 1.0f;
13286                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13287         }
13288         if (dynamic)
13289                 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);
13290         else
13291                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13292                         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);
13293 }
13294 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)
13295 {
13296         matrix4x4_t projection;
13297         decalsystem_t *decalsystem;
13298         qboolean dynamic;
13299         dp_model_t *model;
13300         const msurface_t *surface;
13301         const msurface_t *surfaces;
13302         const int *surfacelist;
13303         const texture_t *texture;
13304         int numtriangles;
13305         int numsurfacelist;
13306         int surfacelistindex;
13307         int surfaceindex;
13308         int triangleindex;
13309         float localorigin[3];
13310         float localnormal[3];
13311         float localmins[3];
13312         float localmaxs[3];
13313         float localsize;
13314         //float normal[3];
13315         float planes[6][4];
13316         float angles[3];
13317         bih_t *bih;
13318         int bih_triangles_count;
13319         int bih_triangles[256];
13320         int bih_surfaces[256];
13321
13322         decalsystem = &ent->decalsystem;
13323         model = ent->model;
13324         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13325         {
13326                 R_DecalSystem_Reset(&ent->decalsystem);
13327                 return;
13328         }
13329
13330         if (!model->brush.data_nodes && !cl_decals_models.integer)
13331         {
13332                 if (decalsystem->model)
13333                         R_DecalSystem_Reset(decalsystem);
13334                 return;
13335         }
13336
13337         if (decalsystem->model != model)
13338                 R_DecalSystem_Reset(decalsystem);
13339         decalsystem->model = model;
13340
13341         RSurf_ActiveModelEntity(ent, false, false, false);
13342
13343         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13344         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13345         VectorNormalize(localnormal);
13346         localsize = worldsize*rsurface.inversematrixscale;
13347         localmins[0] = localorigin[0] - localsize;
13348         localmins[1] = localorigin[1] - localsize;
13349         localmins[2] = localorigin[2] - localsize;
13350         localmaxs[0] = localorigin[0] + localsize;
13351         localmaxs[1] = localorigin[1] + localsize;
13352         localmaxs[2] = localorigin[2] + localsize;
13353
13354         //VectorCopy(localnormal, planes[4]);
13355         //VectorVectors(planes[4], planes[2], planes[0]);
13356         AnglesFromVectors(angles, localnormal, NULL, false);
13357         AngleVectors(angles, planes[0], planes[2], planes[4]);
13358         VectorNegate(planes[0], planes[1]);
13359         VectorNegate(planes[2], planes[3]);
13360         VectorNegate(planes[4], planes[5]);
13361         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13362         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13363         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13364         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13365         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13366         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13367
13368 #if 1
13369 // works
13370 {
13371         matrix4x4_t forwardprojection;
13372         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13373         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13374 }
13375 #else
13376 // broken
13377 {
13378         float projectionvector[4][3];
13379         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13380         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13381         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13382         projectionvector[0][0] = planes[0][0] * ilocalsize;
13383         projectionvector[0][1] = planes[1][0] * ilocalsize;
13384         projectionvector[0][2] = planes[2][0] * ilocalsize;
13385         projectionvector[1][0] = planes[0][1] * ilocalsize;
13386         projectionvector[1][1] = planes[1][1] * ilocalsize;
13387         projectionvector[1][2] = planes[2][1] * ilocalsize;
13388         projectionvector[2][0] = planes[0][2] * ilocalsize;
13389         projectionvector[2][1] = planes[1][2] * ilocalsize;
13390         projectionvector[2][2] = planes[2][2] * ilocalsize;
13391         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13392         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13393         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13394         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13395 }
13396 #endif
13397
13398         dynamic = model->surfmesh.isanimated;
13399         numsurfacelist = model->nummodelsurfaces;
13400         surfacelist = model->sortedmodelsurfaces;
13401         surfaces = model->data_surfaces;
13402
13403         bih = NULL;
13404         bih_triangles_count = -1;
13405         if(!dynamic)
13406         {
13407                 if(model->render_bih.numleafs)
13408                         bih = &model->render_bih;
13409                 else if(model->collision_bih.numleafs)
13410                         bih = &model->collision_bih;
13411         }
13412         if(bih)
13413                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13414         if(bih_triangles_count == 0)
13415                 return;
13416         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13417                 return;
13418         if(bih_triangles_count > 0)
13419         {
13420                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13421                 {
13422                         surfaceindex = bih_surfaces[triangleindex];
13423                         surface = surfaces + surfaceindex;
13424                         texture = surface->texture;
13425                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13426                                 continue;
13427                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13428                                 continue;
13429                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13430                 }
13431         }
13432         else
13433         {
13434                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13435                 {
13436                         surfaceindex = surfacelist[surfacelistindex];
13437                         surface = surfaces + surfaceindex;
13438                         // check cull box first because it rejects more than any other check
13439                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13440                                 continue;
13441                         // skip transparent surfaces
13442                         texture = surface->texture;
13443                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13444                                 continue;
13445                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13446                                 continue;
13447                         numtriangles = surface->num_triangles;
13448                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13449                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13450                 }
13451         }
13452 }
13453
13454 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13455 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)
13456 {
13457         int renderentityindex;
13458         float worldmins[3];
13459         float worldmaxs[3];
13460         entity_render_t *ent;
13461
13462         if (!cl_decals_newsystem.integer)
13463                 return;
13464
13465         worldmins[0] = worldorigin[0] - worldsize;
13466         worldmins[1] = worldorigin[1] - worldsize;
13467         worldmins[2] = worldorigin[2] - worldsize;
13468         worldmaxs[0] = worldorigin[0] + worldsize;
13469         worldmaxs[1] = worldorigin[1] + worldsize;
13470         worldmaxs[2] = worldorigin[2] + worldsize;
13471
13472         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13473
13474         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13475         {
13476                 ent = r_refdef.scene.entities[renderentityindex];
13477                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13478                         continue;
13479
13480                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13481         }
13482 }
13483
13484 typedef struct r_decalsystem_splatqueue_s
13485 {
13486         vec3_t worldorigin;
13487         vec3_t worldnormal;
13488         float color[4];
13489         float tcrange[4];
13490         float worldsize;
13491         int decalsequence;
13492 }
13493 r_decalsystem_splatqueue_t;
13494
13495 int r_decalsystem_numqueued = 0;
13496 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13497
13498 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)
13499 {
13500         r_decalsystem_splatqueue_t *queue;
13501
13502         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13503                 return;
13504
13505         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13506         VectorCopy(worldorigin, queue->worldorigin);
13507         VectorCopy(worldnormal, queue->worldnormal);
13508         Vector4Set(queue->color, r, g, b, a);
13509         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13510         queue->worldsize = worldsize;
13511         queue->decalsequence = cl.decalsequence++;
13512 }
13513
13514 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13515 {
13516         int i;
13517         r_decalsystem_splatqueue_t *queue;
13518
13519         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13520                 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);
13521         r_decalsystem_numqueued = 0;
13522 }
13523
13524 extern cvar_t cl_decals_max;
13525 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13526 {
13527         int i;
13528         decalsystem_t *decalsystem = &ent->decalsystem;
13529         int numdecals;
13530         int killsequence;
13531         tridecal_t *decal;
13532         float frametime;
13533         float lifetime;
13534
13535         if (!decalsystem->numdecals)
13536                 return;
13537
13538         if (r_showsurfaces.integer)
13539                 return;
13540
13541         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13542         {
13543                 R_DecalSystem_Reset(decalsystem);
13544                 return;
13545         }
13546
13547         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13548         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13549
13550         if (decalsystem->lastupdatetime)
13551                 frametime = (cl.time - decalsystem->lastupdatetime);
13552         else
13553                 frametime = 0;
13554         decalsystem->lastupdatetime = cl.time;
13555         decal = decalsystem->decals;
13556         numdecals = decalsystem->numdecals;
13557
13558         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13559         {
13560                 if (decal->color4ub[0][3])
13561                 {
13562                         decal->lived += frametime;
13563                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13564                         {
13565                                 memset(decal, 0, sizeof(*decal));
13566                                 if (decalsystem->freedecal > i)
13567                                         decalsystem->freedecal = i;
13568                         }
13569                 }
13570         }
13571         decal = decalsystem->decals;
13572         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13573                 numdecals--;
13574
13575         // collapse the array by shuffling the tail decals into the gaps
13576         for (;;)
13577         {
13578                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13579                         decalsystem->freedecal++;
13580                 if (decalsystem->freedecal == numdecals)
13581                         break;
13582                 decal[decalsystem->freedecal] = decal[--numdecals];
13583         }
13584
13585         decalsystem->numdecals = numdecals;
13586
13587         if (numdecals <= 0)
13588         {
13589                 // if there are no decals left, reset decalsystem
13590                 R_DecalSystem_Reset(decalsystem);
13591         }
13592 }
13593
13594 extern skinframe_t *decalskinframe;
13595 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13596 {
13597         int i;
13598         decalsystem_t *decalsystem = &ent->decalsystem;
13599         int numdecals;
13600         tridecal_t *decal;
13601         float faderate;
13602         float alpha;
13603         float *v3f;
13604         float *c4f;
13605         float *t2f;
13606         const int *e;
13607         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13608         int numtris = 0;
13609
13610         numdecals = decalsystem->numdecals;
13611         if (!numdecals)
13612                 return;
13613
13614         if (r_showsurfaces.integer)
13615                 return;
13616
13617         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13618         {
13619                 R_DecalSystem_Reset(decalsystem);
13620                 return;
13621         }
13622
13623         // if the model is static it doesn't matter what value we give for
13624         // wantnormals and wanttangents, so this logic uses only rules applicable
13625         // to a model, knowing that they are meaningless otherwise
13626         if (ent == r_refdef.scene.worldentity)
13627                 RSurf_ActiveWorldEntity();
13628         else
13629                 RSurf_ActiveModelEntity(ent, false, false, false);
13630
13631         decalsystem->lastupdatetime = cl.time;
13632         decal = decalsystem->decals;
13633
13634         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13635
13636         // update vertex positions for animated models
13637         v3f = decalsystem->vertex3f;
13638         c4f = decalsystem->color4f;
13639         t2f = decalsystem->texcoord2f;
13640         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13641         {
13642                 if (!decal->color4ub[0][3])
13643                         continue;
13644
13645                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13646                         continue;
13647
13648                 // update color values for fading decals
13649                 if (decal->lived >= cl_decals_time.value)
13650                 {
13651                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13652                         alpha *= (1.0f/255.0f);
13653                 }
13654                 else
13655                         alpha = 1.0f/255.0f;
13656
13657                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13658                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13659                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13660                 c4f[ 3] = 1;
13661                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13662                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13663                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13664                 c4f[ 7] = 1;
13665                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13666                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13667                 c4f[10] = decal->color4ub[2][2] * alpha;
13668                 c4f[11] = 1;
13669
13670                 t2f[0] = decal->texcoord2f[0][0];
13671                 t2f[1] = decal->texcoord2f[0][1];
13672                 t2f[2] = decal->texcoord2f[1][0];
13673                 t2f[3] = decal->texcoord2f[1][1];
13674                 t2f[4] = decal->texcoord2f[2][0];
13675                 t2f[5] = decal->texcoord2f[2][1];
13676
13677                 // update vertex positions for animated models
13678                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13679                 {
13680                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13681                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13682                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13683                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13684                 }
13685                 else
13686                 {
13687                         VectorCopy(decal->vertex3f[0], v3f);
13688                         VectorCopy(decal->vertex3f[1], v3f + 3);
13689                         VectorCopy(decal->vertex3f[2], v3f + 6);
13690                 }
13691
13692                 if (r_refdef.fogenabled)
13693                 {
13694                         alpha = RSurf_FogVertex(v3f);
13695                         VectorScale(c4f, alpha, c4f);
13696                         alpha = RSurf_FogVertex(v3f + 3);
13697                         VectorScale(c4f + 4, alpha, c4f + 4);
13698                         alpha = RSurf_FogVertex(v3f + 6);
13699                         VectorScale(c4f + 8, alpha, c4f + 8);
13700                 }
13701
13702                 v3f += 9;
13703                 c4f += 12;
13704                 t2f += 6;
13705                 numtris++;
13706         }
13707
13708         if (numtris > 0)
13709         {
13710                 r_refdef.stats.drawndecals += numtris;
13711
13712                 // now render the decals all at once
13713                 // (this assumes they all use one particle font texture!)
13714                 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);
13715                 R_Mesh_ResetTextureState();
13716                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13717                 GL_DepthMask(false);
13718                 GL_DepthRange(0, 1);
13719                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13720                 GL_DepthTest(true);
13721                 GL_CullFace(GL_NONE);
13722                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13723                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13724                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13725         }
13726 }
13727
13728 static void R_DrawModelDecals(void)
13729 {
13730         int i, numdecals;
13731
13732         // fade faster when there are too many decals
13733         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13734         for (i = 0;i < r_refdef.scene.numentities;i++)
13735                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13736
13737         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13738         for (i = 0;i < r_refdef.scene.numentities;i++)
13739                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13740                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13741
13742         R_DecalSystem_ApplySplatEntitiesQueue();
13743
13744         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13745         for (i = 0;i < r_refdef.scene.numentities;i++)
13746                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13747
13748         r_refdef.stats.totaldecals += numdecals;
13749
13750         if (r_showsurfaces.integer)
13751                 return;
13752
13753         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13754
13755         for (i = 0;i < r_refdef.scene.numentities;i++)
13756         {
13757                 if (!r_refdef.viewcache.entityvisible[i])
13758                         continue;
13759                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13760                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13761         }
13762 }
13763
13764 extern cvar_t mod_collision_bih;
13765 void R_DrawDebugModel(void)
13766 {
13767         entity_render_t *ent = rsurface.entity;
13768         int i, j, k, l, flagsmask;
13769         const msurface_t *surface;
13770         dp_model_t *model = ent->model;
13771         vec3_t v;
13772
13773         switch(vid.renderpath)
13774         {
13775         case RENDERPATH_GL11:
13776         case RENDERPATH_GL13:
13777         case RENDERPATH_GL20:
13778         case RENDERPATH_CGGL:
13779                 break;
13780         case RENDERPATH_D3D9:
13781                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13782                 return;
13783         case RENDERPATH_D3D10:
13784                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13785                 return;
13786         case RENDERPATH_D3D11:
13787                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13788                 return;
13789         }
13790
13791         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13792
13793         R_Mesh_ResetTextureState();
13794         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13795         GL_DepthRange(0, 1);
13796         GL_DepthTest(!r_showdisabledepthtest.integer);
13797         GL_DepthMask(false);
13798         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13799
13800         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13801         {
13802                 int triangleindex;
13803                 int bihleafindex;
13804                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13805                 const q3mbrush_t *brush;
13806                 const bih_t *bih = &model->collision_bih;
13807                 const bih_leaf_t *bihleaf;
13808                 float vertex3f[3][3];
13809                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13810                 cullbox = false;
13811                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13812                 {
13813                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13814                                 continue;
13815                         switch (bihleaf->type)
13816                         {
13817                         case BIH_BRUSH:
13818                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13819                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13820                                 {
13821                                         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);
13822                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13823                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13824                                 }
13825                                 break;
13826                         case BIH_COLLISIONTRIANGLE:
13827                                 triangleindex = bihleaf->itemindex;
13828                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13829                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13830                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13831                                 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);
13832                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13833                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13834                                 break;
13835                         case BIH_RENDERTRIANGLE:
13836                                 triangleindex = bihleaf->itemindex;
13837                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13838                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13839                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13840                                 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);
13841                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13842                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13843                                 break;
13844                         }
13845                 }
13846         }
13847
13848         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13849
13850         if (r_showtris.integer || r_shownormals.integer)
13851         {
13852                 if (r_showdisabledepthtest.integer)
13853                 {
13854                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13855                         GL_DepthMask(false);
13856                 }
13857                 else
13858                 {
13859                         GL_BlendFunc(GL_ONE, GL_ZERO);
13860                         GL_DepthMask(true);
13861                 }
13862                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13863                 {
13864                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13865                                 continue;
13866                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13867                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13868                         {
13869                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13870                                 if (r_showtris.value > 0)
13871                                 {
13872                                         if (!rsurface.texture->currentlayers->depthmask)
13873                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13874                                         else if (ent == r_refdef.scene.worldentity)
13875                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13876                                         else
13877                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13878                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13879                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13880                                         RSurf_DrawBatch();
13881                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13882                                         CHECKGLERROR
13883                                 }
13884                                 if (r_shownormals.value < 0)
13885                                 {
13886                                         qglBegin(GL_LINES);
13887                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13888                                         {
13889                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13890                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13891                                                 qglVertex3f(v[0], v[1], v[2]);
13892                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13893                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13894                                                 qglVertex3f(v[0], v[1], v[2]);
13895                                         }
13896                                         qglEnd();
13897                                         CHECKGLERROR
13898                                 }
13899                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13900                                 {
13901                                         qglBegin(GL_LINES);
13902                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13903                                         {
13904                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13905                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13906                                                 qglVertex3f(v[0], v[1], v[2]);
13907                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13908                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13909                                                 qglVertex3f(v[0], v[1], v[2]);
13910                                         }
13911                                         qglEnd();
13912                                         CHECKGLERROR
13913                                         qglBegin(GL_LINES);
13914                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13915                                         {
13916                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13917                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13918                                                 qglVertex3f(v[0], v[1], v[2]);
13919                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13920                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13921                                                 qglVertex3f(v[0], v[1], v[2]);
13922                                         }
13923                                         qglEnd();
13924                                         CHECKGLERROR
13925                                         qglBegin(GL_LINES);
13926                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13927                                         {
13928                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13929                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13930                                                 qglVertex3f(v[0], v[1], v[2]);
13931                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13932                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13933                                                 qglVertex3f(v[0], v[1], v[2]);
13934                                         }
13935                                         qglEnd();
13936                                         CHECKGLERROR
13937                                 }
13938                         }
13939                 }
13940                 rsurface.texture = NULL;
13941         }
13942 }
13943
13944 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13945 int r_maxsurfacelist = 0;
13946 const msurface_t **r_surfacelist = NULL;
13947 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13948 {
13949         int i, j, endj, flagsmask;
13950         dp_model_t *model = r_refdef.scene.worldmodel;
13951         msurface_t *surfaces;
13952         unsigned char *update;
13953         int numsurfacelist = 0;
13954         if (model == NULL)
13955                 return;
13956
13957         if (r_maxsurfacelist < model->num_surfaces)
13958         {
13959                 r_maxsurfacelist = model->num_surfaces;
13960                 if (r_surfacelist)
13961                         Mem_Free((msurface_t**)r_surfacelist);
13962                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13963         }
13964
13965         RSurf_ActiveWorldEntity();
13966
13967         surfaces = model->data_surfaces;
13968         update = model->brushq1.lightmapupdateflags;
13969
13970         // update light styles on this submodel
13971         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13972         {
13973                 model_brush_lightstyleinfo_t *style;
13974                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13975                 {
13976                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13977                         {
13978                                 int *list = style->surfacelist;
13979                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13980                                 for (j = 0;j < style->numsurfaces;j++)
13981                                         update[list[j]] = true;
13982                         }
13983                 }
13984         }
13985
13986         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13987
13988         if (debug)
13989         {
13990                 R_DrawDebugModel();
13991                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13992                 return;
13993         }
13994
13995         rsurface.lightmaptexture = NULL;
13996         rsurface.deluxemaptexture = NULL;
13997         rsurface.uselightmaptexture = false;
13998         rsurface.texture = NULL;
13999         rsurface.rtlight = NULL;
14000         numsurfacelist = 0;
14001         // add visible surfaces to draw list
14002         for (i = 0;i < model->nummodelsurfaces;i++)
14003         {
14004                 j = model->sortedmodelsurfaces[i];
14005                 if (r_refdef.viewcache.world_surfacevisible[j])
14006                         r_surfacelist[numsurfacelist++] = surfaces + j;
14007         }
14008         // update lightmaps if needed
14009         if (model->brushq1.firstrender)
14010         {
14011                 model->brushq1.firstrender = false;
14012                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14013                         if (update[j])
14014                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14015         }
14016         else if (update)
14017         {
14018                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14019                         if (r_refdef.viewcache.world_surfacevisible[j])
14020                                 if (update[j])
14021                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14022         }
14023         // don't do anything if there were no surfaces
14024         if (!numsurfacelist)
14025         {
14026                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14027                 return;
14028         }
14029         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14030         GL_AlphaTest(false);
14031
14032         // add to stats if desired
14033         if (r_speeds.integer && !skysurfaces && !depthonly)
14034         {
14035                 r_refdef.stats.world_surfaces += numsurfacelist;
14036                 for (j = 0;j < numsurfacelist;j++)
14037                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14038         }
14039
14040         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14041 }
14042
14043 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14044 {
14045         int i, j, endj, flagsmask;
14046         dp_model_t *model = ent->model;
14047         msurface_t *surfaces;
14048         unsigned char *update;
14049         int numsurfacelist = 0;
14050         if (model == NULL)
14051                 return;
14052
14053         if (r_maxsurfacelist < model->num_surfaces)
14054         {
14055                 r_maxsurfacelist = model->num_surfaces;
14056                 if (r_surfacelist)
14057                         Mem_Free((msurface_t **)r_surfacelist);
14058                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14059         }
14060
14061         // if the model is static it doesn't matter what value we give for
14062         // wantnormals and wanttangents, so this logic uses only rules applicable
14063         // to a model, knowing that they are meaningless otherwise
14064         if (ent == r_refdef.scene.worldentity)
14065                 RSurf_ActiveWorldEntity();
14066         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14067                 RSurf_ActiveModelEntity(ent, false, false, false);
14068         else if (prepass)
14069                 RSurf_ActiveModelEntity(ent, true, true, true);
14070         else if (depthonly)
14071         {
14072                 switch (vid.renderpath)
14073                 {
14074                 case RENDERPATH_GL20:
14075                 case RENDERPATH_CGGL:
14076                 case RENDERPATH_D3D9:
14077                 case RENDERPATH_D3D10:
14078                 case RENDERPATH_D3D11:
14079                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14080                         break;
14081                 case RENDERPATH_GL13:
14082                 case RENDERPATH_GL11:
14083                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14084                         break;
14085                 }
14086         }
14087         else
14088         {
14089                 switch (vid.renderpath)
14090                 {
14091                 case RENDERPATH_GL20:
14092                 case RENDERPATH_CGGL:
14093                 case RENDERPATH_D3D9:
14094                 case RENDERPATH_D3D10:
14095                 case RENDERPATH_D3D11:
14096                         RSurf_ActiveModelEntity(ent, true, true, false);
14097                         break;
14098                 case RENDERPATH_GL13:
14099                 case RENDERPATH_GL11:
14100                         RSurf_ActiveModelEntity(ent, true, false, false);
14101                         break;
14102                 }
14103         }
14104
14105         surfaces = model->data_surfaces;
14106         update = model->brushq1.lightmapupdateflags;
14107
14108         // update light styles
14109         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14110         {
14111                 model_brush_lightstyleinfo_t *style;
14112                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14113                 {
14114                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14115                         {
14116                                 int *list = style->surfacelist;
14117                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14118                                 for (j = 0;j < style->numsurfaces;j++)
14119                                         update[list[j]] = true;
14120                         }
14121                 }
14122         }
14123
14124         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14125
14126         if (debug)
14127         {
14128                 R_DrawDebugModel();
14129                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14130                 return;
14131         }
14132
14133         rsurface.lightmaptexture = NULL;
14134         rsurface.deluxemaptexture = NULL;
14135         rsurface.uselightmaptexture = false;
14136         rsurface.texture = NULL;
14137         rsurface.rtlight = NULL;
14138         numsurfacelist = 0;
14139         // add visible surfaces to draw list
14140         for (i = 0;i < model->nummodelsurfaces;i++)
14141                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14142         // don't do anything if there were no surfaces
14143         if (!numsurfacelist)
14144         {
14145                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14146                 return;
14147         }
14148         // update lightmaps if needed
14149         if (update)
14150         {
14151                 int updated = 0;
14152                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14153                 {
14154                         if (update[j])
14155                         {
14156                                 updated++;
14157                                 R_BuildLightMap(ent, surfaces + j);
14158                         }
14159                 }
14160         }
14161         if (update)
14162                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14163                         if (update[j])
14164                                 R_BuildLightMap(ent, surfaces + j);
14165         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14166         GL_AlphaTest(false);
14167
14168         // add to stats if desired
14169         if (r_speeds.integer && !skysurfaces && !depthonly)
14170         {
14171                 r_refdef.stats.entities_surfaces += numsurfacelist;
14172                 for (j = 0;j < numsurfacelist;j++)
14173                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14174         }
14175
14176         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14177 }
14178
14179 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14180 {
14181         static texture_t texture;
14182         static msurface_t surface;
14183         const msurface_t *surfacelist = &surface;
14184
14185         // fake enough texture and surface state to render this geometry
14186
14187         texture.update_lastrenderframe = -1; // regenerate this texture
14188         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14189         texture.currentskinframe = skinframe;
14190         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14191         texture.offsetmapping = OFFSETMAPPING_OFF;
14192         texture.offsetscale = 1;
14193         texture.specularscalemod = 1;
14194         texture.specularpowermod = 1;
14195
14196         surface.texture = &texture;
14197         surface.num_triangles = numtriangles;
14198         surface.num_firsttriangle = firsttriangle;
14199         surface.num_vertices = numvertices;
14200         surface.num_firstvertex = firstvertex;
14201
14202         // now render it
14203         rsurface.texture = R_GetCurrentTexture(surface.texture);
14204         rsurface.lightmaptexture = NULL;
14205         rsurface.deluxemaptexture = NULL;
14206         rsurface.uselightmaptexture = false;
14207         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14208 }
14209
14210 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)
14211 {
14212         static msurface_t surface;
14213         const msurface_t *surfacelist = &surface;
14214
14215         // fake enough texture and surface state to render this geometry
14216
14217         surface.texture = texture;
14218         surface.num_triangles = numtriangles;
14219         surface.num_firsttriangle = firsttriangle;
14220         surface.num_vertices = numvertices;
14221         surface.num_firstvertex = firstvertex;
14222
14223         // now render it
14224         rsurface.texture = R_GetCurrentTexture(surface.texture);
14225         rsurface.lightmaptexture = NULL;
14226         rsurface.deluxemaptexture = NULL;
14227         rsurface.uselightmaptexture = false;
14228         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14229 }