]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix almost all g++ -pedantic warnings
[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 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
592 "#endif\n"
593 "\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "#   extension GL_EXT_gpu_shader4 : enable\n"
597 "# endif\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "#   extension GL_ARB_texture_gather : enable\n"
600 "# else\n"
601 "#   ifdef GL_AMD_texture_texture4\n"
602 "#     extension GL_AMD_texture_texture4 : enable\n"
603 "#   endif\n"
604 "# endif\n"
605 "#endif\n"
606 "\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
609 "#endif\n"
610 "\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
613 "//#endif\n"
614 "\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
620 "//#else\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
625 "//#endif\n"
626 "\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#endif\n"
630 "\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "}\n"
637 "#endif\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
639 "\n"
640 "\n"
641 "\n"
642 "\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
649 "}\n"
650 "#endif\n"
651 "\n"
652 "#ifdef FRAGMENT_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_FragColor = gl_Color;\n"
656 "}\n"
657 "#endif\n"
658 "#else // !MODE_SHOWDEPTH\n"
659 "\n"
660 "\n"
661 "\n"
662 "\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
666 "\n"
667 "#ifdef VERTEX_SHADER\n"
668 "void main(void)\n"
669 "{\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 "#ifdef USEBLOOM\n"
673 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
674 "#endif\n"
675 "}\n"
676 "#endif\n"
677 "\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
680 "#ifdef USEBLOOM\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
683 "#endif\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
686 "#endif\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
692 "#endif\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
700 "void main(void)\n"
701 "{\n"
702 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 "#ifdef USEBLOOM\n"
704 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#endif\n"
706 "#ifdef USEVIEWTINT\n"
707 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
713 "       float sobel = 1.0;\n"
714 "       // vec2 ts = textureSize(Texture_First, 0);\n"
715 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 "       vec2 px = PixelSize;\n"
717 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
719 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
722 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
725 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
728 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#endif\n"
750 "\n"
751 "#ifdef USESATURATION\n"
752 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#endif\n"
757 "\n"
758 "#ifdef USEGAMMARAMPS\n"
759 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
762 "#endif\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_POSTPROCESS\n"
766 "\n"
767 "\n"
768 "\n"
769 "\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
773 "#endif\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
776 "#endif\n"
777 "#ifdef VERTEX_SHADER\n"
778 "void main(void)\n"
779 "{\n"
780 "       gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
783 "#endif\n"
784 "#ifdef USESPECULAR\n"
785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
786 "#endif\n"
787 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
788 "}\n"
789 "#endif\n"
790 "\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
797 "#endif\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#endif\n"
805 "\n"
806 "#ifdef USESPECULAR\n"
807 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 "       gl_FragColor *= tex2;\n"
810 "# endif\n"
811 "# ifdef USEGLOW\n"
812 "       gl_FragColor += tex2;\n"
813 "# endif\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
816 "# endif\n"
817 "#endif\n"
818 "}\n"
819 "#endif\n"
820 "#else // !MODE_GENERIC\n"
821 "\n"
822 "\n"
823 "\n"
824 "\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
828 "void main(void)\n"
829 "{\n"
830 "       gl_FrontColor = gl_Color;\n"
831 "       TexCoord = gl_MultiTexCoord0.xy;\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "}\n"
834 "#endif\n"
835 "\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
839 "\n"
840 "void main(void)\n"
841 "{\n"
842 "       int i;\n"
843 "       vec2 tc = TexCoord;\n"
844 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 "       tc += BloomBlur_Parameters.xy;\n"
846 "       for (i = 1;i < SAMPLES;i++)\n"
847 "       {\n"
848 "               color += texture2D(Texture_First, tc).rgb;\n"
849 "               tc += BloomBlur_Parameters.xy;\n"
850 "       }\n"
851 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
860 "\n"
861 "void main(void)\n"
862 "{\n"
863 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 "       ModelViewProjectionPosition = gl_Position;\n"
866 "}\n"
867 "#endif\n"
868 "\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
873 "\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 "       // FIXME temporary hack to detect the case that the reflection\n"
889 "       // gets blackened at edges due to leaving the area that contains actual\n"
890 "       // content.\n"
891 "       // Remove this 'ack once we have a better way to stop this thing from\n"
892 "       // 'appening.\n"
893 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
899 "}\n"
900 "#endif\n"
901 "#else // !MODE_REFRACTION\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
913 "\n"
914 "void main(void)\n"
915 "{\n"
916 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 "       ModelViewProjectionPosition = gl_Position;\n"
923 "}\n"
924 "#endif\n"
925 "\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
930 "\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
938 "\n"
939 "void main(void)\n"
940 "{\n"
941 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 "       // FIXME temporary hack to detect the case that the reflection\n"
947 "       // gets blackened at edges due to leaving the area that contains actual\n"
948 "       // content.\n"
949 "       // Remove this 'ack once we have a better way to stop this thing from\n"
950 "       // 'appening.\n"
951 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
963 "}\n"
964 "#endif\n"
965 "#else // !MODE_WATER\n"
966 "\n"
967 "\n"
968 "\n"
969 "\n"
970 "// common definitions between vertex shader and fragment shader:\n"
971 "\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
975 "#endif\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
982 "#endif\n"
983 "\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
986 "#endif\n"
987 "\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
990 "#endif\n"
991 "#ifdef USEFOG\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
993 "#endif\n"
994 "\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1003 "#endif\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1011 "#endif\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1015 "#endif\n"
1016 "uniform vec4 FogPlane;\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1020 "#endif\n"
1021 "\n"
1022 "\n"
1023 "\n"
1024 "\n"
1025 "\n"
1026 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1027 "\n"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1030 "\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1034 "#ifdef USEGLOW\n"
1035 "uniform sampler2D Texture_Glow;\n"
1036 "#endif\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1041 "#ifdef USEGLOW\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1043 "#endif\n"
1044 "#endif\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1048 "#endif\n"
1049 "#ifdef USEFOG\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1052 "#endif\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1054 "#endif\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1057 "#endif\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1060 "#endif\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1068 "#endif\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1072 "#endif\n"
1073 "\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1077 "\n"
1078 "#ifdef USEFOG\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1083 "{\n"
1084 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1086 "       float fogfrac;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 "       fogfrac = fogheightpixel.a;\n"
1090 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1091 "#else\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1094 "# else\n"
1095 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1096 "# endif\n"
1097 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1098 "#endif\n"
1099 "}\n"
1100 "#endif\n"
1101 "\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1105 "{\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 "       // 14 sample relief mapping: linear search and then binary search\n"
1108 "       // this basically steps forward a small amount repeatedly until it finds\n"
1109 "       // itself inside solid, then jitters forward and back using decreasing\n"
1110 "       // amounts to find the impact\n"
1111 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 "       vec3 RT = vec3(TexCoord, 1);\n"
1115 "       OffsetVector *= 0.1;\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1118 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1126 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1127 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1128 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1130 "       return RT.xy;\n"
1131 "#else\n"
1132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 "       // this basically moves forward the full distance, and then backs up based\n"
1134 "       // on height of samples\n"
1135 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 "       TexCoord += OffsetVector;\n"
1139 "       OffsetVector *= 0.333;\n"
1140 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 "       return TexCoord;\n"
1144 "#endif\n"
1145 "}\n"
1146 "#endif // USEOFFSETMAPPING\n"
1147 "\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1151 "#endif\n"
1152 "\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1158 "# else\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1160 "# endif\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1166 "# else\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1168 "# endif\n"
1169 "#endif\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1178 "# else\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1180 "# endif\n"
1181 "#endif\n"
1182 "\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1186 "#endif\n"
1187 "\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1191 "# else\n"
1192 "#  ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1194 "{\n"
1195 "       vec3 adir = abs(dir);\n"
1196 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1199 "}\n"
1200 "#  else\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       float ma = adir.z;\n"
1205 "       vec4 proj = vec4(dir, 2.5);\n"
1206 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1210 "}\n"
1211 "#  endif\n"
1212 "# endif\n"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1217 "{\n"
1218 "       vec3 adir = abs(dir);\n"
1219 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1220 "}\n"
1221 "#endif\n"
1222 "\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1225 "{\n"
1226 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "       float f;\n"
1228 "#  ifdef USESHADOWSAMPLER\n"
1229 "\n"
1230 "#    ifdef USESHADOWMAPPCF\n"
1231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1233 "#    else\n"
1234 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1235 "#    endif\n"
1236 "\n"
1237 "#  else\n"
1238 "\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1244 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1245 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1246 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1247 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1249 "#      else\n"
1250 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 "       vec2 offset = fract(shadowmaptc.xy);\n"
1252 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1254 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1255 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1257 "#      endif\n"
1258 "#    else\n"
1259 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1260 "#    endif\n"
1261 "\n"
1262 "#  endif\n"
1263 "#  ifdef USESHADOWMAPORTHO\n"
1264 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1265 "#  else\n"
1266 "       return f;\n"
1267 "#  endif\n"
1268 "}\n"
1269 "# endif\n"
1270 "\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1273 "{\n"
1274 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1275 "       float f;\n"
1276 "\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "#    ifdef USESHADOWMAPPCF\n"
1279 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1280 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1282 "#    else\n"
1283 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1284 "#    endif\n"
1285 "#  else\n"
1286 "#    ifdef USESHADOWMAPPCF\n"
1287 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "#      ifdef GL_ARB_texture_gather\n"
1289 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1290 "#      else\n"
1291 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1292 "#      endif\n"
1293 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "#      if USESHADOWMAPPCF > 1\n"
1295 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1299 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1300 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1301 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1302 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1303 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1304 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 "       locols.yz += group2.ab;\n"
1307 "       hicols.yz += group8.rg;\n"
1308 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 "                               mix(locols, hicols, offset.y);\n"
1311 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 "       f = dot(cols, vec4(1.0/25.0));\n"
1314 "#      else\n"
1315 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1318 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1319 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1322 "#      endif\n"
1323 "#     else\n"
1324 "#      ifdef GL_EXT_gpu_shader4\n"
1325 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1326 "#      else\n"
1327 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1328 "#      endif\n"
1329 "#      if USESHADOWMAPPCF > 1\n"
1330 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 "       center *= ShadowMap_TextureScale;\n"
1332 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1333 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1334 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1335 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1336 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      else\n"
1339 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1342 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1343 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1345 "#      endif\n"
1346 "#     endif\n"
1347 "#    else\n"
1348 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1349 "#    endif\n"
1350 "#  endif\n"
1351 "#  ifdef USESHADOWMAPORTHO\n"
1352 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1353 "#  else\n"
1354 "       return f;\n"
1355 "#  endif\n"
1356 "}\n"
1357 "# endif\n"
1358 "\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1361 "{\n"
1362 "       // apply depth texture cubemap as light filter\n"
1363 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1364 "       float f;\n"
1365 "#  ifdef USESHADOWSAMPLER\n"
1366 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1367 "#  else\n"
1368 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1369 "#  endif\n"
1370 "       return f;\n"
1371 "}\n"
1372 "# endif\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#endif\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1386 "void main(void)\n"
1387 "{\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#endif\n"
1393 "\n"
1394 "       // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1400 "#endif\n"
1401 "\n"
1402 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "void main(void)\n"
1411 "{\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 "       // apply offsetmapping\n"
1414 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1416 "#endif\n"
1417 "\n"
1418 "#ifdef USEALPHAKILL\n"
1419 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1420 "               discard;\n"
1421 "#endif\n"
1422 "\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1433 "#else\n"
1434 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1436 "#endif\n"
1437 "\n"
1438 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1439 "}\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1442 "\n"
1443 "\n"
1444 "\n"
1445 "\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1449 "void main(void)\n"
1450 "{\n"
1451 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1465 "#endif\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1467 "void main(void)\n"
1468 "{\n"
1469 "       // calculate viewspace pixel position\n"
1470 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1471 "       vec3 position;\n"
1472 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 "       // decode viewspace pixel normal\n"
1475 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 "       // surfacenormal = pixel normal in viewspace\n"
1478 "       // LightVector = pixel to light in viewspace\n"
1479 "       // CubeVector = position in lightspace\n"
1480 "       // eyevector = pixel to view in viewspace\n"
1481 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 "       // calculate diffuse shading\n"
1485 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1487 "#endif\n"
1488 "#ifdef USESPECULAR\n"
1489 "       // calculate directional shading\n"
1490 "       vec3 eyevector = position * -1.0;\n"
1491 "#  ifdef USEEXACTSPECULARMATH\n"
1492 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1493 "#  else\n"
1494 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1496 "#  endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 "       fade *= ShadowMapCompare(CubeVector);\n"
1501 "#endif\n"
1502 "\n"
1503 "#ifdef USEDIFFUSE\n"
1504 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1505 "#else\n"
1506 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1507 "#endif\n"
1508 "#ifdef USESPECULAR\n"
1509 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1510 "#else\n"
1511 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1512 "#endif\n"
1513 "\n"
1514 "# ifdef USECUBEFILTER\n"
1515 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 "       gl_FragData[0].rgb *= cubecolor;\n"
1517 "       gl_FragData[1].rgb *= cubecolor;\n"
1518 "# endif\n"
1519 "}\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1522 "\n"
1523 "\n"
1524 "\n"
1525 "\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1530 "#endif\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1533 "#endif\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1536 "#endif\n"
1537 "void main(void)\n"
1538 "{\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 "       gl_FrontColor = gl_Color;\n"
1541 "#endif\n"
1542 "       // copy the surface texcoord\n"
1543 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1546 "#endif\n"
1547 "#ifdef USELIGHTMAP\n"
1548 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1549 "#endif\n"
1550 "\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 "       // transform vertex position into light attenuation/cubemap space\n"
1553 "       // (-1 to +1 across the light box)\n"
1554 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1555 "\n"
1556 "# ifdef USEDIFFUSE\n"
1557 "       // transform unnormalized light direction into tangent space\n"
1558 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 "       //  normalize it per pixel)\n"
1560 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1564 "# endif\n"
1565 "#endif\n"
1566 "\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1571 "#endif\n"
1572 "\n"
1573 "       // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1579 "#endif\n"
1580 "\n"
1581 "#ifdef USEFOG\n"
1582 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1584 "#endif\n"
1585 "\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1588 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1589 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1590 "#endif\n"
1591 "\n"
1592 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1594 "\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1597 "#endif\n"
1598 "\n"
1599 "#ifdef USEREFLECTION\n"
1600 "       ModelViewProjectionPosition = gl_Position;\n"
1601 "#endif\n"
1602 "}\n"
1603 "#endif // VERTEX_SHADER\n"
1604 "\n"
1605 "\n"
1606 "\n"
1607 "\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1613 "#endif\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1618 "#ifdef USEGLOW\n"
1619 "uniform myhalf3 Color_Glow;\n"
1620 "#endif\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1627 "#endif\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1632 "#endif\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1635 "#endif\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1638 "#endif\n"
1639 "void main(void)\n"
1640 "{\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 "       // apply offsetmapping\n"
1643 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1645 "#endif\n"
1646 "\n"
1647 "       // combine the diffuse textures (base, pants, shirt)\n"
1648 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 "       if (color.a < 0.5)\n"
1651 "               discard;\n"
1652 "#endif\n"
1653 "       color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1656 "#endif\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1662 "       color.a = 1.0;\n"
1663 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1664 "#endif\n"
1665 "\n"
1666 "       // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1669 "#else\n"
1670 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1671 "#endif\n"
1672 "\n"
1673 "       // get the material colors\n"
1674 "       myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1678 "# else\n"
1679 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1680 "# endif\n"
1681 "#endif\n"
1682 "\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1702 "#else\n"
1703 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1705 "#endif\n"
1706 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1707 "#endif\n"
1708 "#else\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif\n"
1711 "       color.rgb *= LightColor;\n"
1712 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1715 "#endif\n"
1716 "# ifdef USECUBEFILTER\n"
1717 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1718 "# endif\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1725 "#define SHADING\n"
1726 "#ifdef USEDIFFUSE\n"
1727 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1728 "#endif\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "       // convert modelspace light vector to tangentspace\n"
1737 "       myhalf3 lightnormal;\n"
1738 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1753 "#define SHADING\n"
1754 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1757 "#endif\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 "       color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef SHADING\n"
1776 "# ifdef USEDIFFUSE\n"
1777 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "#  ifdef USESPECULAR\n"
1779 "#   ifdef USEEXACTSPECULARMATH\n"
1780 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1781 "#   else\n"
1782 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1784 "#   endif\n"
1785 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1786 "#  else\n"
1787 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1788 "#  endif\n"
1789 "# else\n"
1790 "       color.rgb = diffusetex * Color_Ambient;\n"
1791 "# endif\n"
1792 "#endif\n"
1793 "\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEGLOW\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1807 "#else\n"
1808 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1809 "#endif\n"
1810 "#endif\n"
1811 "\n"
1812 "#ifdef USEFOG\n"
1813 "       color.rgb = FogVertex(color.rgb);\n"
1814 "#endif\n"
1815 "\n"
1816 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1817 "#ifdef USEREFLECTION\n"
1818 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 "       // FIXME temporary hack to detect the case that the reflection\n"
1823 "       // gets blackened at edges due to leaving the area that contains actual\n"
1824 "       // content.\n"
1825 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1826 "       // 'appening.\n"
1827 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1833 "#endif\n"
1834 "\n"
1835 "       gl_FragColor = vec4(color);\n"
1836 "}\n"
1837 "#endif // FRAGMENT_SHADER\n"
1838 "\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1848 ;
1849
1850 /*
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868
1869
1870
1871 =========================================================================================================================================================
1872
1873
1874
1875 =========================================================================================================================================================
1876 */
1877
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1882 "\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1886 "#endif\n"
1887 "\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1889 "# define USEFOG\n"
1890 "#endif\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1893 "#endif\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "#ifdef HLSL\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1903 "#else\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1905 "#endif\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1916 ")\n"
1917 "{\n"
1918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 "       Depth = gl_Position.z;\n"
1920 "}\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1928 ")\n"
1929 "{\n"
1930 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 "       temp.yz -= floor(temp.yz);\n"
1933 "       gl_FragColor = float4(temp,0);\n"
1934 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1935 "}\n"
1936 "#endif\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "       gl_FragColor = gl_FrontColor;\n"
1965 "}\n"
1966 "#endif\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1973 "\n"
1974 "#ifdef VERTEX_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 "#ifdef USEBLOOM\n"
1989 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1990 "#endif\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2000 "#ifdef USEBLOOM\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2002 "#endif\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2005 "#endif\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2008 "#endif\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2011 "#endif\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2020 ")\n"
2021 "{\n"
2022 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2023 "#ifdef USEBLOOM\n"
2024 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2033 "       float sobel = 1.0;\n"
2034 "       // float2 ts = textureSize(Texture_First, 0);\n"
2035 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 "       float2 px = PixelSize;\n"
2037 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2039 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2042 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2045 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2048 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2066 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2067 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef USESATURATION\n"
2072 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2103 ")\n"
2104 "{\n"
2105 "#ifdef HLSL\n"
2106 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2107 "#else\n"
2108 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2109 "#endif\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "       gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef USESPECULAR\n"
2142 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 "       gl_FragColor *= tex2;\n"
2145 "# endif\n"
2146 "# ifdef USEGLOW\n"
2147 "       gl_FragColor += tex2;\n"
2148 "# endif\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2151 "# endif\n"
2152 "#endif\n"
2153 "}\n"
2154 "#endif\n"
2155 "#else // !MODE_GENERIC\n"
2156 "\n"
2157 "\n"
2158 "\n"
2159 "\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2162 "void main\n"
2163 "(\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2169 ")\n"
2170 "{\n"
2171 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2172 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "\n"
2178 "void main\n"
2179 "(\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2184 ")\n"
2185 "{\n"
2186 "       int i;\n"
2187 "       float2 tc = TexCoord;\n"
2188 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 "       tc += BloomBlur_Parameters.xy;\n"
2190 "       for (i = 1;i < SAMPLES;i++)\n"
2191 "       {\n"
2192 "               color += tex2D(Texture_First, tc).rgb;\n"
2193 "               tc += BloomBlur_Parameters.xy;\n"
2194 "       }\n"
2195 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2196 "}\n"
2197 "#endif\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2201 "void main\n"
2202 "(\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2212 ")\n"
2213 "{\n"
2214 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 "       ModelViewProjectionPosition = gl_Position;\n"
2217 "}\n"
2218 "#endif\n"
2219 "\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2221 "void main\n"
2222 "(\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2238 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 "       // FIXME temporary hack to detect the case that the reflection\n"
2241 "       // gets blackened at edges due to leaving the area that contains actual\n"
2242 "       // content.\n"
2243 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2244 "       // 'appening.\n"
2245 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_REFRACTION\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2260 "\n"
2261 "void main\n"
2262 "(\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2275 ")\n"
2276 "{\n"
2277 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 "       ModelViewProjectionPosition = gl_Position;\n"
2284 "}\n"
2285 "#endif\n"
2286 "\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2288 "void main\n"
2289 "(\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2304 ")\n"
2305 "{\n"
2306 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xyxy * DistortScaleRefractReflect;\n"
2311 "       // FIXME temporary hack to detect the case that the reflection\n"
2312 "       // gets blackened at edges due to leaving the area that contains actual\n"
2313 "       // content.\n"
2314 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2315 "       // 'appening.\n"
2316 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2328 "}\n"
2329 "#endif\n"
2330 "#else // !MODE_WATER\n"
2331 "\n"
2332 "\n"
2333 "\n"
2334 "\n"
2335 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2336 "\n"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2339 "\n"
2340 "#ifdef USEFOG\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2342 "{\n"
2343 "       float fogfrac;\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 "       fogfrac = fogheightpixel.a;\n"
2347 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2348 "#else\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2351 "# else\n"
2352 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2353 "# endif\n"
2354 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2355 "#endif\n"
2356 "}\n"
2357 "#endif\n"
2358 "\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2361 "{\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 "       // 14 sample relief mapping: linear search and then binary search\n"
2364 "       // this basically steps forward a small amount repeatedly until it finds\n"
2365 "       // itself inside solid, then jitters forward and back using decreasing\n"
2366 "       // amounts to find the impact\n"
2367 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 "       float3 RT = float3(TexCoord, 1);\n"
2371 "       OffsetVector *= 0.1;\n"
2372 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2382 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2383 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2384 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2386 "       return RT.xy;\n"
2387 "#else\n"
2388 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 "       // this basically moves forward the full distance, and then backs up based\n"
2390 "       // on height of samples\n"
2391 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 "       TexCoord += OffsetVector;\n"
2395 "       OffsetVector *= 0.333;\n"
2396 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2438 "{\n"
2439 "       float3 adir = abs(dir);\n"
2440 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2441 "}\n"
2442 "#endif\n"
2443 "\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2447 "#else\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2449 "#endif\n"
2450 "{\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2453 "#else\n"
2454 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2455 "#endif\n"
2456 "       float f;\n"
2457 "#  ifdef USESHADOWSAMPLER\n"
2458 "\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2462 "#    else\n"
2463 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2464 "#    endif\n"
2465 "\n"
2466 "#  else\n"
2467 "\n"
2468 "#    ifdef USESHADOWMAPPCF\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2474 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2475 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 "       float2 offset = frac(shadowmaptc.xy);\n"
2481 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2483 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2484 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2486 "#      endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2489 "#    endif\n"
2490 "\n"
2491 "#  endif\n"
2492 "#  ifdef USESHADOWMAPORTHO\n"
2493 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2494 "#  else\n"
2495 "       return f;\n"
2496 "#  endif\n"
2497 "}\n"
2498 "# endif\n"
2499 "\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2503 "#else\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2505 "#endif\n"
2506 "{\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2509 "#else\n"
2510 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2511 "#endif\n"
2512 "       float f;\n"
2513 "\n"
2514 "#  ifdef USESHADOWSAMPLER\n"
2515 "#    ifdef USESHADOWMAPPCF\n"
2516 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2517 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2519 "#    else\n"
2520 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2521 "#    endif\n"
2522 "#  else\n"
2523 "#    ifdef USESHADOWMAPPCF\n"
2524 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "#      ifdef GL_ARB_texture_gather\n"
2526 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2529 "#      endif\n"
2530 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "#      if USESHADOWMAPPCF > 1\n"
2532 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2536 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2537 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2538 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2539 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2540 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2541 "       float4 locols = float4(group1.ab, group3.ab);\n"
2542 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2543 "       locols.yz += group2.ab;\n"
2544 "       hicols.yz += group8.rg;\n"
2545 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 "                               lerp(locols, hicols, offset.y);\n"
2548 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 "       f = dot(cols, float4(1.0/25.0));\n"
2551 "#      else\n"
2552 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2555 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2556 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2559 "#      endif\n"
2560 "#     else\n"
2561 "#      ifdef GL_EXT_gpu_shader4\n"
2562 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2563 "#      else\n"
2564 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2565 "#      endif\n"
2566 "#      if USESHADOWMAPPCF > 1\n"
2567 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 "       center *= ShadowMap_TextureScale;\n"
2569 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2570 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2571 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2572 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2573 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2575 "#      else\n"
2576 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2579 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2580 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2582 "#      endif\n"
2583 "#     endif\n"
2584 "#    else\n"
2585 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2586 "#    endif\n"
2587 "#  endif\n"
2588 "#  ifdef USESHADOWMAPORTHO\n"
2589 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2590 "#  else\n"
2591 "       return f;\n"
2592 "#  endif\n"
2593 "}\n"
2594 "# endif\n"
2595 "\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2598 "{\n"
2599 "       // apply depth texture cubemap as light filter\n"
2600 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2601 "       float f;\n"
2602 "#  ifdef USESHADOWSAMPLER\n"
2603 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2604 "#  else\n"
2605 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2606 "#  endif\n"
2607 "       return f;\n"
2608 "}\n"
2609 "# endif\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\n"
2617 "#ifdef VERTEX_SHADER\n"
2618 "void main\n"
2619 "(\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2624 "#endif\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2632 "#endif\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2636 "#endif\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#endif\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2646 ")\n"
2647 "{\n"
2648 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "#ifdef HLSL\n"
2651 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2652 "#else\n"
2653 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2654 "#endif\n"
2655 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2656 "#endif\n"
2657 "\n"
2658 "       // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2664 "#endif\n"
2665 "\n"
2666 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2670 "}\n"
2671 "#endif // VERTEX_SHADER\n"
2672 "\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2674 "void main\n"
2675 "(\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2684 "#endif\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2689 "#endif\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2692 "#endif\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2695 ")\n"
2696 "{\n"
2697 "       float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 "       // apply offsetmapping\n"
2700 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEALPHAKILL\n"
2705 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2706 "               discard;\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2719 "#else\n"
2720 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2722 "#endif\n"
2723 "\n"
2724 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2725 "}\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2728 "\n"
2729 "\n"
2730 "\n"
2731 "\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2734 "void main\n"
2735 "(\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2741 ")\n"
2742 "{\n"
2743 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2745 "}\n"
2746 "#endif // VERTEX_SHADER\n"
2747 "\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2749 "void main\n"
2750 "(\n"
2751 "#ifdef HLSL\n"
2752 "float2 Pixel : VPOS,\n"
2753 "#else\n"
2754 "float2 Pixel : WPOS,\n"
2755 "#endif\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2766 "#endif\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2770 "\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2778 "# else\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2786 "# else\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2788 "# endif\n"
2789 "#endif\n"
2790 "\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2798 "# else\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2800 "# endif\n"
2801 "#endif\n"
2802 "\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2806 "#endif\n"
2807 "\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2810 ")\n"
2811 "{\n"
2812 "       // calculate viewspace pixel position\n"
2813 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 "       float3 position;\n"
2816 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 "       // decode viewspace pixel normal\n"
2819 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 "       // surfacenormal = pixel normal in viewspace\n"
2822 "       // LightVector = pixel to light in viewspace\n"
2823 "       // CubeVector = position in lightspace\n"
2824 "       // eyevector = pixel to view in viewspace\n"
2825 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 "       // calculate diffuse shading\n"
2829 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2831 "#endif\n"
2832 "#ifdef USESPECULAR\n"
2833 "       // calculate directional shading\n"
2834 "       float3 eyevector = position * -1.0;\n"
2835 "#  ifdef USEEXACTSPECULARMATH\n"
2836 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2837 "#  else\n"
2838 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2840 "#  endif\n"
2841 "#endif\n"
2842 "\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 "       fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2847 "# endif\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2850 "# endif\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2853 "# endif\n"
2854 "\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2857 "#endif\n"
2858 "       );\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USEDIFFUSE\n"
2862 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2863 "#else\n"
2864 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2865 "#endif\n"
2866 "#ifdef USESPECULAR\n"
2867 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2868 "#else\n"
2869 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2870 "#endif\n"
2871 "\n"
2872 "# ifdef USECUBEFILTER\n"
2873 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 "       gl_FragData0.rgb *= cubecolor;\n"
2875 "       gl_FragData1.rgb *= cubecolor;\n"
2876 "# endif\n"
2877 "}\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2880 "\n"
2881 "\n"
2882 "\n"
2883 "\n"
2884 "#ifdef VERTEX_SHADER\n"
2885 "void main\n"
2886 "(\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2891 "#endif\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2897 "\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2902 "#endif\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2911 "#endif\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2915 "#endif\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2918 "#endif\n"
2919 "\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2924 "#endif\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2927 "#endif\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "#endif\n"
2931 "#ifdef USEFOG\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2933 "#endif\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2936 "#endif\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "out float4 gl_Position : POSITION\n"
2949 ")\n"
2950 "{\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2952 "#ifdef HLSL\n"
2953 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2954 "#else\n"
2955 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2956 "#endif\n"
2957 "#endif\n"
2958 "       // copy the surface texcoord\n"
2959 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2962 "#endif\n"
2963 "#ifdef USELIGHTMAP\n"
2964 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2965 "#endif\n"
2966 "\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 "       // transform vertex position into light attenuation/cubemap space\n"
2969 "       // (-1 to +1 across the light box)\n"
2970 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2971 "\n"
2972 "# ifdef USEDIFFUSE\n"
2973 "       // transform unnormalized light direction into tangent space\n"
2974 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 "       //  normalize it per pixel)\n"
2976 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2980 "# endif\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2987 "#endif\n"
2988 "\n"
2989 "       // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEFOG\n"
2998 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3004 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3005 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3006 "#endif\n"
3007 "\n"
3008 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3010 "\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USEREFLECTION\n"
3016 "       ModelViewProjectionPosition = gl_Position;\n"
3017 "#endif\n"
3018 "}\n"
3019 "#endif // VERTEX_SHADER\n"
3020 "\n"
3021 "\n"
3022 "\n"
3023 "\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3025 "void main\n"
3026 "(\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "#ifdef HLSL\n"
3029 "float2 Pixel : VPOS,\n"
3030 "#else\n"
3031 "float2 Pixel : WPOS,\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3038 "#endif\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3041 "#endif\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3044 "#endif\n"
3045 "#ifdef USEFOG\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3047 "#endif\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3050 "#endif\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3053 "#endif\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3056 "#endif\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3061 "#endif\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3064 "#endif\n"
3065 "\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3070 "#endif\n"
3071 "#ifdef USEGLOW\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3073 "#endif\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3079 "#endif\n"
3080 "#ifdef USEGLOW\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3082 "#endif\n"
3083 "#endif\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3087 "#endif\n"
3088 "#ifdef USEFOG\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3091 "#endif\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3094 "#endif\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3097 "#endif\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3105 "#endif\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3114 "#endif\n"
3115 "#ifdef USEFOG\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3120 "#endif\n"
3121 "\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3130 "#endif\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3135 "#ifdef USEGLOW\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3137 "#endif\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3144 "#endif\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3149 "#endif\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3152 "#endif\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3155 "#endif\n"
3156 "\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3160 "#endif\n"
3161 "\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3163 "\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3167 "# else\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3169 "# endif\n"
3170 "#endif\n"
3171 "\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3175 "# else\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3177 "# endif\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3182 "#endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3187 "# else\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3189 "# endif\n"
3190 "#endif\n"
3191 "\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3195 "#endif\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3197 "\n"
3198 "out float4 gl_FragColor : COLOR\n"
3199 ")\n"
3200 "{\n"
3201 "       float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3204 "#endif\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 "       // apply offsetmapping\n"
3207 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3209 "#endif\n"
3210 "\n"
3211 "       // combine the diffuse textures (base, pants, shirt)\n"
3212 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 "       if (color.a < 0.5)\n"
3215 "               discard;\n"
3216 "#endif\n"
3217 "       color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3220 "#endif\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3226 "       color.a = 1.0;\n"
3227 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3228 "#endif\n"
3229 "\n"
3230 "       // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3233 "#else\n"
3234 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3235 "#endif\n"
3236 "\n"
3237 "       // get the material colors\n"
3238 "       half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3242 "# else\n"
3243 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3244 "# endif\n"
3245 "#endif\n"
3246 "\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3252 "#endif\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 "       // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 "       half3 lightnormal = half3(normalize(LightVector));\n"
3261 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3266 "#else\n"
3267 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3269 "#endif\n"
3270 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3271 "#endif\n"
3272 "#else\n"
3273 "       color.rgb = diffusetex * Color_Ambient;\n"
3274 "#endif\n"
3275 "       color.rgb *= LightColor;\n"
3276 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3281 "# endif\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3284 "# endif\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3287 "# endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3291 "#endif\n"
3292 "       ));\n"
3293 "\n"
3294 "#endif\n"
3295 "# ifdef USECUBEFILTER\n"
3296 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3297 "# endif\n"
3298 "\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3305 "#else\n"
3306 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "//     color.r = half(shadowmaptc.z);\n"
3314 "#endif\n"
3315 "//     color.r = 1;\n"
3316 "#endif\n"
3317 "//     color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3319 "\n"
3320 "\n"
3321 "\n"
3322 "\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3324 "#define SHADING\n"
3325 "#ifdef USEDIFFUSE\n"
3326 "       half3 lightnormal = half3(normalize(LightVector));\n"
3327 "#endif\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3331 "#define SHADING\n"
3332 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 "       // convert modelspace light vector to tangentspace\n"
3336 "       half3 lightnormal;\n"
3337 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3352 "#define SHADING\n"
3353 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3356 "#endif\n"
3357 "\n"
3358 "\n"
3359 "\n"
3360 "\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 "       color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3370 "\n"
3371 "\n"
3372 "\n"
3373 "\n"
3374 "#ifdef SHADING\n"
3375 "# ifdef USEDIFFUSE\n"
3376 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "#  ifdef USESPECULAR\n"
3378 "#   ifdef USEEXACTSPECULARMATH\n"
3379 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3380 "#   else\n"
3381 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3383 "#   endif\n"
3384 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3385 "#  else\n"
3386 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3387 "#  endif\n"
3388 "# else\n"
3389 "       color.rgb = diffusetex * Color_Ambient;\n"
3390 "# endif\n"
3391 "#endif\n"
3392 "\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3397 "# endif\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3400 "# endif\n"
3401 "       );\n"
3402 "#endif\n"
3403 "\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef USEGLOW\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3413 "#else\n"
3414 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3415 "#endif\n"
3416 "#endif\n"
3417 "\n"
3418 "#ifdef USEFOG\n"
3419 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3420 "#endif\n"
3421 "\n"
3422 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3423 "#ifdef USEREFLECTION\n"
3424 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 "       // FIXME temporary hack to detect the case that the reflection\n"
3429 "       // gets blackened at edges due to leaving the area that contains actual\n"
3430 "       // content.\n"
3431 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3432 "       // 'appening.\n"
3433 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3439 "#endif\n"
3440 "\n"
3441 "       gl_FragColor = float4(color);\n"
3442 "}\n"
3443 "#endif // FRAGMENT_SHADER\n"
3444 "\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3454 ;
3455
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3459
3460 //=======================================================================================================================================================
3461
3462 typedef struct shaderpermutationinfo_s
3463 {
3464         const char *pretext;
3465         const char *name;
3466 }
3467 shaderpermutationinfo_t;
3468
3469 typedef struct shadermodeinfo_s
3470 {
3471         const char *vertexfilename;
3472         const char *geometryfilename;
3473         const char *fragmentfilename;
3474         const char *pretext;
3475         const char *name;
3476 }
3477 shadermodeinfo_t;
3478
3479 typedef enum shaderpermutation_e
3480 {
3481         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3512 }
3513 shaderpermutation_t;
3514
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3517 {
3518         {"#define USEDIFFUSE\n", " diffuse"},
3519         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520         {"#define USEVIEWTINT\n", " viewtint"},
3521         {"#define USECOLORMAPPING\n", " colormapping"},
3522         {"#define USESATURATION\n", " saturation"},
3523         {"#define USEFOGINSIDE\n", " foginside"},
3524         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526         {"#define USEGAMMARAMPS\n", " gammaramps"},
3527         {"#define USECUBEFILTER\n", " cubefilter"},
3528         {"#define USEGLOW\n", " glow"},
3529         {"#define USEBLOOM\n", " bloom"},
3530         {"#define USESPECULAR\n", " specular"},
3531         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533         {"#define USEREFLECTION\n", " reflection"},
3534         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545         {"#define USEALPHAKILL\n", " alphakill"},
3546         {"#define USEREFLECTCUBE\n", " reflectcube"},
3547 };
3548
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3551 {
3552         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3567         SHADERMODE_COUNT
3568 }
3569 shadermode_t;
3570
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3573 {
3574         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3589 };
3590
3591 #ifdef SUPPORTCG
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3593 {
3594         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3609 };
3610 #endif
3611
3612 #ifdef SUPPORTD3D
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3614 {
3615         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3630 };
3631 #endif
3632
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_glsl_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         int program;
3645         /// locations of detected uniforms in program object, or -1 if not found
3646         int loc_Texture_First;
3647         int loc_Texture_Second;
3648         int loc_Texture_GammaRamps;
3649         int loc_Texture_Normal;
3650         int loc_Texture_Color;
3651         int loc_Texture_Gloss;
3652         int loc_Texture_Glow;
3653         int loc_Texture_SecondaryNormal;
3654         int loc_Texture_SecondaryColor;
3655         int loc_Texture_SecondaryGloss;
3656         int loc_Texture_SecondaryGlow;
3657         int loc_Texture_Pants;
3658         int loc_Texture_Shirt;
3659         int loc_Texture_FogHeightTexture;
3660         int loc_Texture_FogMask;
3661         int loc_Texture_Lightmap;
3662         int loc_Texture_Deluxemap;
3663         int loc_Texture_Attenuation;
3664         int loc_Texture_Cube;
3665         int loc_Texture_Refraction;
3666         int loc_Texture_Reflection;
3667         int loc_Texture_ShadowMapRect;
3668         int loc_Texture_ShadowMapCube;
3669         int loc_Texture_ShadowMap2D;
3670         int loc_Texture_CubeProjection;
3671         int loc_Texture_ScreenDepth;
3672         int loc_Texture_ScreenNormalMap;
3673         int loc_Texture_ScreenDiffuse;
3674         int loc_Texture_ScreenSpecular;
3675         int loc_Texture_ReflectMask;
3676         int loc_Texture_ReflectCube;
3677         int loc_Alpha;
3678         int loc_BloomBlur_Parameters;
3679         int loc_ClientTime;
3680         int loc_Color_Ambient;
3681         int loc_Color_Diffuse;
3682         int loc_Color_Specular;
3683         int loc_Color_Glow;
3684         int loc_Color_Pants;
3685         int loc_Color_Shirt;
3686         int loc_DeferredColor_Ambient;
3687         int loc_DeferredColor_Diffuse;
3688         int loc_DeferredColor_Specular;
3689         int loc_DeferredMod_Diffuse;
3690         int loc_DeferredMod_Specular;
3691         int loc_DistortScaleRefractReflect;
3692         int loc_EyePosition;
3693         int loc_FogColor;
3694         int loc_FogHeightFade;
3695         int loc_FogPlane;
3696         int loc_FogPlaneViewDist;
3697         int loc_FogRangeRecip;
3698         int loc_LightColor;
3699         int loc_LightDir;
3700         int loc_LightPosition;
3701         int loc_OffsetMapping_Scale;
3702         int loc_PixelSize;
3703         int loc_ReflectColor;
3704         int loc_ReflectFactor;
3705         int loc_ReflectOffset;
3706         int loc_RefractColor;
3707         int loc_Saturation;
3708         int loc_ScreenCenterRefractReflect;
3709         int loc_ScreenScaleRefractReflect;
3710         int loc_ScreenToDepth;
3711         int loc_ShadowMap_Parameters;
3712         int loc_ShadowMap_TextureScale;
3713         int loc_SpecularPower;
3714         int loc_UserVec1;
3715         int loc_UserVec2;
3716         int loc_UserVec3;
3717         int loc_UserVec4;
3718         int loc_ViewTintColor;
3719         int loc_ViewToLight;
3720         int loc_ModelToLight;
3721         int loc_TexMatrix;
3722         int loc_BackgroundTexMatrix;
3723         int loc_ModelViewProjectionMatrix;
3724         int loc_ModelViewMatrix;
3725         int loc_PixelToScreenTexCoord;
3726         int loc_ModelToReflectCube;
3727         int loc_ShadowMapMatrix;
3728         int loc_BloomColorSubtract;
3729 }
3730 r_glsl_permutation_t;
3731
3732 #define SHADERPERMUTATION_HASHSIZE 256
3733
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3740
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3742 {
3743         //unsigned int hashdepth = 0;
3744         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745         r_glsl_permutation_t *p;
3746         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3747         {
3748                 if (p->mode == mode && p->permutation == permutation)
3749                 {
3750                         //if (hashdepth > 10)
3751                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3752                         return p;
3753                 }
3754                 //hashdepth++;
3755         }
3756         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3757         p->mode = mode;
3758         p->permutation = permutation;
3759         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760         r_glsl_permutationhash[mode][hashindex] = p;
3761         //if (hashdepth > 10)
3762         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3763         return p;
3764 }
3765
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3767 {
3768         char *shaderstring;
3769         if (!filename || !filename[0])
3770                 return NULL;
3771         if (!strcmp(filename, "glsl/default.glsl"))
3772         {
3773                 if (!glslshaderstring)
3774                 {
3775                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776                         if (glslshaderstring)
3777                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3778                         else
3779                                 glslshaderstring = (char *)builtinshaderstring;
3780                 }
3781                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783                 return shaderstring;
3784         }
3785         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3786         if (shaderstring)
3787         {
3788                 if (printfromdisknotice)
3789                         Con_DPrintf("from disk %s... ", filename);
3790                 return shaderstring;
3791         }
3792         return shaderstring;
3793 }
3794
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3796 {
3797         int i;
3798         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799         int vertstrings_count = 0;
3800         int geomstrings_count = 0;
3801         int fragstrings_count = 0;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         const char *vertstrings_list[32+3];
3804         const char *geomstrings_list[32+3];
3805         const char *fragstrings_list[32+3];
3806         char permutationname[256];
3807
3808         if (p->compiled)
3809                 return;
3810         p->compiled = true;
3811         p->program = 0;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         // compile the shader program
3865         if (vertstrings_count + geomstrings_count + fragstrings_count)
3866                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3867         if (p->program)
3868         {
3869                 CHECKGLERROR
3870                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871                 // look up all the uniform variable names we care about, so we don't
3872                 // have to look them up every time we set them
3873
3874                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3875                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3876                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3879                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3906                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3908                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3911                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3912                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3913                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3921                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3922                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3924                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3927                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3928                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3929                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3931                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3932                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3935                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3936                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3942                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3943                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3944                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3945                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3946                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3948                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3949                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3950                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957                 // initialize the samplers to refer to the texture units we use
3958                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3959                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3960                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3961                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3962                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3963                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3964                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3965                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3969                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3970                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3971                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3973                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3974                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3975                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3976                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3977                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3978                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3979                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3988                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3989                 CHECKGLERROR
3990                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3991         }
3992         else
3993                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3994
3995         // free the strings
3996         if (vertexstring)
3997                 Mem_Free(vertexstring);
3998         if (geometrystring)
3999                 Mem_Free(geometrystring);
4000         if (fragmentstring)
4001                 Mem_Free(fragmentstring);
4002 }
4003
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4005 {
4006         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007         if (r_glsl_permutation != perm)
4008         {
4009                 r_glsl_permutation = perm;
4010                 if (!r_glsl_permutation->program)
4011                 {
4012                         if (!r_glsl_permutation->compiled)
4013                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4014                         if (!r_glsl_permutation->program)
4015                         {
4016                                 // remove features until we find a valid permutation
4017                                 int i;
4018                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4019                                 {
4020                                         // reduce i more quickly whenever it would not remove any bits
4021                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022                                         if (!(permutation & j))
4023                                                 continue;
4024                                         permutation -= j;
4025                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026                                         if (!r_glsl_permutation->compiled)
4027                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4028                                         if (r_glsl_permutation->program)
4029                                                 break;
4030                                 }
4031                                 if (i >= SHADERPERMUTATION_COUNT)
4032                                 {
4033                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035                                         qglUseProgramObjectARB(0);CHECKGLERROR
4036                                         return; // no bit left to clear, entire mode is broken
4037                                 }
4038                         }
4039                 }
4040                 CHECKGLERROR
4041                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4042         }
4043         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4046 }
4047
4048 #ifdef SUPPORTCG
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4052 {
4053         /// hash lookup data
4054         struct r_cg_permutation_s *hashnext;
4055         unsigned int mode;
4056         unsigned int permutation;
4057
4058         /// indicates if we have tried compiling this permutation already
4059         qboolean compiled;
4060         /// 0 if compilation failed
4061         CGprogram vprogram;
4062         CGprogram fprogram;
4063         /// locations of detected parameters in programs, or NULL if not found
4064         CGparameter vp_EyePosition;
4065         CGparameter vp_FogPlane;
4066         CGparameter vp_LightDir;
4067         CGparameter vp_LightPosition;
4068         CGparameter vp_ModelToLight;
4069         CGparameter vp_TexMatrix;
4070         CGparameter vp_BackgroundTexMatrix;
4071         CGparameter vp_ModelViewProjectionMatrix;
4072         CGparameter vp_ModelViewMatrix;
4073         CGparameter vp_ShadowMapMatrix;
4074
4075         CGparameter fp_Texture_First;
4076         CGparameter fp_Texture_Second;
4077         CGparameter fp_Texture_GammaRamps;
4078         CGparameter fp_Texture_Normal;
4079         CGparameter fp_Texture_Color;
4080         CGparameter fp_Texture_Gloss;
4081         CGparameter fp_Texture_Glow;
4082         CGparameter fp_Texture_SecondaryNormal;
4083         CGparameter fp_Texture_SecondaryColor;
4084         CGparameter fp_Texture_SecondaryGloss;
4085         CGparameter fp_Texture_SecondaryGlow;
4086         CGparameter fp_Texture_Pants;
4087         CGparameter fp_Texture_Shirt;
4088         CGparameter fp_Texture_FogHeightTexture;
4089         CGparameter fp_Texture_FogMask;
4090         CGparameter fp_Texture_Lightmap;
4091         CGparameter fp_Texture_Deluxemap;
4092         CGparameter fp_Texture_Attenuation;
4093         CGparameter fp_Texture_Cube;
4094         CGparameter fp_Texture_Refraction;
4095         CGparameter fp_Texture_Reflection;
4096         CGparameter fp_Texture_ShadowMapRect;
4097         CGparameter fp_Texture_ShadowMapCube;
4098         CGparameter fp_Texture_ShadowMap2D;
4099         CGparameter fp_Texture_CubeProjection;
4100         CGparameter fp_Texture_ScreenDepth;
4101         CGparameter fp_Texture_ScreenNormalMap;
4102         CGparameter fp_Texture_ScreenDiffuse;
4103         CGparameter fp_Texture_ScreenSpecular;
4104         CGparameter fp_Texture_ReflectMask;
4105         CGparameter fp_Texture_ReflectCube;
4106         CGparameter fp_Alpha;
4107         CGparameter fp_BloomBlur_Parameters;
4108         CGparameter fp_ClientTime;
4109         CGparameter fp_Color_Ambient;
4110         CGparameter fp_Color_Diffuse;
4111         CGparameter fp_Color_Specular;
4112         CGparameter fp_Color_Glow;
4113         CGparameter fp_Color_Pants;
4114         CGparameter fp_Color_Shirt;
4115         CGparameter fp_DeferredColor_Ambient;
4116         CGparameter fp_DeferredColor_Diffuse;
4117         CGparameter fp_DeferredColor_Specular;
4118         CGparameter fp_DeferredMod_Diffuse;
4119         CGparameter fp_DeferredMod_Specular;
4120         CGparameter fp_DistortScaleRefractReflect;
4121         CGparameter fp_EyePosition;
4122         CGparameter fp_FogColor;
4123         CGparameter fp_FogHeightFade;
4124         CGparameter fp_FogPlane;
4125         CGparameter fp_FogPlaneViewDist;
4126         CGparameter fp_FogRangeRecip;
4127         CGparameter fp_LightColor;
4128         CGparameter fp_LightDir;
4129         CGparameter fp_LightPosition;
4130         CGparameter fp_OffsetMapping_Scale;
4131         CGparameter fp_PixelSize;
4132         CGparameter fp_ReflectColor;
4133         CGparameter fp_ReflectFactor;
4134         CGparameter fp_ReflectOffset;
4135         CGparameter fp_RefractColor;
4136         CGparameter fp_Saturation;
4137         CGparameter fp_ScreenCenterRefractReflect;
4138         CGparameter fp_ScreenScaleRefractReflect;
4139         CGparameter fp_ScreenToDepth;
4140         CGparameter fp_ShadowMap_Parameters;
4141         CGparameter fp_ShadowMap_TextureScale;
4142         CGparameter fp_SpecularPower;
4143         CGparameter fp_UserVec1;
4144         CGparameter fp_UserVec2;
4145         CGparameter fp_UserVec3;
4146         CGparameter fp_UserVec4;
4147         CGparameter fp_ViewTintColor;
4148         CGparameter fp_ViewToLight;
4149         CGparameter fp_PixelToScreenTexCoord;
4150         CGparameter fp_ModelToReflectCube;
4151         CGparameter fp_BloomColorSubtract;
4152 }
4153 r_cg_permutation_t;
4154
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4161
4162 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4163
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4165 {
4166         //unsigned int hashdepth = 0;
4167         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168         r_cg_permutation_t *p;
4169         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4170         {
4171                 if (p->mode == mode && p->permutation == permutation)
4172                 {
4173                         //if (hashdepth > 10)
4174                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4175                         return p;
4176                 }
4177                 //hashdepth++;
4178         }
4179         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4180         p->mode = mode;
4181         p->permutation = permutation;
4182         p->hashnext = r_cg_permutationhash[mode][hashindex];
4183         r_cg_permutationhash[mode][hashindex] = p;
4184         //if (hashdepth > 10)
4185         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4186         return p;
4187 }
4188
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4190 {
4191         char *shaderstring;
4192         if (!filename || !filename[0])
4193                 return NULL;
4194         if (!strcmp(filename, "cg/default.cg"))
4195         {
4196                 if (!cgshaderstring)
4197                 {
4198                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4199                         if (cgshaderstring)
4200                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4201                         else
4202                                 cgshaderstring = (char *)builtincgshaderstring;
4203                 }
4204                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206                 return shaderstring;
4207         }
4208         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4209         if (shaderstring)
4210         {
4211                 if (printfromdisknotice)
4212                         Con_DPrintf("from disk %s... ", filename);
4213                 return shaderstring;
4214         }
4215         return shaderstring;
4216 }
4217
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4219 {
4220         // TODO: load or create .fp and .vp shader files
4221 }
4222
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4224 {
4225         int i;
4226         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227         int vertstrings_count = 0, vertstring_length = 0;
4228         int geomstrings_count = 0, geomstring_length = 0;
4229         int fragstrings_count = 0, fragstring_length = 0;
4230         char *t;
4231         char *vertexstring, *geometrystring, *fragmentstring;
4232         char *vertstring, *geomstring, *fragstring;
4233         const char *vertstrings_list[32+3];
4234         const char *geomstrings_list[32+3];
4235         const char *fragstrings_list[32+3];
4236         char permutationname[256];
4237         char cachename[256];
4238         CGprofile vertexProfile;
4239         CGprofile fragmentProfile;
4240
4241         if (p->compiled)
4242                 return;
4243         p->compiled = true;
4244         p->vprogram = NULL;
4245         p->fprogram = NULL;
4246
4247         permutationname[0] = 0;
4248         cachename[0] = 0;
4249         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4250         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4252
4253         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254         strlcat(cachename, "cg/", sizeof(cachename));
4255
4256         // the first pretext is which type of shader to compile as
4257         // (later these will all be bound together as a program object)
4258         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4261
4262         // the second pretext is the mode (for example a light source)
4263         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267         strlcat(cachename, modeinfo->name, sizeof(cachename));
4268
4269         // now add all the permutation pretexts
4270         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271         {
4272                 if (permutation & (1<<i))
4273                 {
4274                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4279                 }
4280                 else
4281                 {
4282                         // keep line numbers correct
4283                         vertstrings_list[vertstrings_count++] = "\n";
4284                         geomstrings_list[geomstrings_count++] = "\n";
4285                         fragstrings_list[fragstrings_count++] = "\n";
4286                 }
4287         }
4288
4289         // replace spaces in the cachename with _ characters
4290         for (i = 0;cachename[i];i++)
4291                 if (cachename[i] == ' ')
4292                         cachename[i] = '_';
4293
4294         // now append the shader text itself
4295         vertstrings_list[vertstrings_count++] = vertexstring;
4296         geomstrings_list[geomstrings_count++] = geometrystring;
4297         fragstrings_list[fragstrings_count++] = fragmentstring;
4298
4299         // if any sources were NULL, clear the respective list
4300         if (!vertexstring)
4301                 vertstrings_count = 0;
4302         if (!geometrystring)
4303                 geomstrings_count = 0;
4304         if (!fragmentstring)
4305                 fragstrings_count = 0;
4306
4307         vertstring_length = 0;
4308         for (i = 0;i < vertstrings_count;i++)
4309                 vertstring_length += strlen(vertstrings_list[i]);
4310         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4313
4314         geomstring_length = 0;
4315         for (i = 0;i < geomstrings_count;i++)
4316                 geomstring_length += strlen(geomstrings_list[i]);
4317         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4320
4321         fragstring_length = 0;
4322         for (i = 0;i < fragstrings_count;i++)
4323                 fragstring_length += strlen(fragstrings_list[i]);
4324         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4327
4328         CHECKGLERROR
4329         CHECKCGERROR
4330         //vertexProfile = CG_PROFILE_ARBVP1;
4331         //fragmentProfile = CG_PROFILE_ARBFP1;
4332         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4337         CHECKGLERROR
4338
4339         // try to load the cached shader, or generate one
4340         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4341
4342         // if caching failed, do a dynamic compile for now
4343         CHECKCGERROR
4344         if (vertstring[0] && !p->vprogram)
4345                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4346         CHECKCGERROR
4347         if (fragstring[0] && !p->fprogram)
4348                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4349         CHECKCGERROR
4350
4351         // look up all the uniform variable names we care about, so we don't
4352         // have to look them up every time we set them
4353         if (p->vprogram)
4354         {
4355                 CHECKCGERROR
4356                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4359                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4360                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4361                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4362                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4368                 CHECKCGERROR
4369         }
4370         if (p->fprogram)
4371         {
4372                 CHECKCGERROR
4373                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4376                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4407                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4409                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4422                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4423                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4425                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4428                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4429                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4430                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4432                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4436                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4437                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4444                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4445                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4446                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4447                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4452                 CHECKCGERROR
4453         }
4454
4455         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4457         else
4458                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4459
4460         // free the strings
4461         if (vertstring)
4462                 Mem_Free(vertstring);
4463         if (geomstring)
4464                 Mem_Free(geomstring);
4465         if (fragstring)
4466                 Mem_Free(fragstring);
4467         if (vertexstring)
4468                 Mem_Free(vertexstring);
4469         if (geometrystring)
4470                 Mem_Free(geometrystring);
4471         if (fragmentstring)
4472                 Mem_Free(fragmentstring);
4473 }
4474
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4476 {
4477         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4478         CHECKGLERROR
4479         CHECKCGERROR
4480         if (r_cg_permutation != perm)
4481         {
4482                 r_cg_permutation = perm;
4483                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4484                 {
4485                         if (!r_cg_permutation->compiled)
4486                                 R_CG_CompilePermutation(perm, mode, permutation);
4487                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4488                         {
4489                                 // remove features until we find a valid permutation
4490                                 int i;
4491                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4492                                 {
4493                                         // reduce i more quickly whenever it would not remove any bits
4494                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495                                         if (!(permutation & j))
4496                                                 continue;
4497                                         permutation -= j;
4498                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499                                         if (!r_cg_permutation->compiled)
4500                                                 R_CG_CompilePermutation(perm, mode, permutation);
4501                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4502                                                 break;
4503                                 }
4504                                 if (i >= SHADERPERMUTATION_COUNT)
4505                                 {
4506                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508                                         return; // no bit left to clear, entire mode is broken
4509                                 }
4510                         }
4511                 }
4512                 CHECKGLERROR
4513                 CHECKCGERROR
4514                 if (r_cg_permutation->vprogram)
4515                 {
4516                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4519                 }
4520                 else
4521                 {
4522                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4524                 }
4525                 if (r_cg_permutation->fprogram)
4526                 {
4527                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4530                 }
4531                 else
4532                 {
4533                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4535                 }
4536         }
4537         CHECKCGERROR
4538         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4541 }
4542
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4544 {
4545         cgGLSetTextureParameter(param, R_GetTexture(tex));
4546         cgGLEnableTextureParameter(param);
4547 }
4548 #endif
4549
4550 #ifdef SUPPORTD3D
4551
4552 #ifdef SUPPORTD3D
4553 #include <d3d9.h>
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4556 #endif
4557
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4560 {
4561         /// hash lookup data
4562         struct r_hlsl_permutation_s *hashnext;
4563         unsigned int mode;
4564         unsigned int permutation;
4565
4566         /// indicates if we have tried compiling this permutation already
4567         qboolean compiled;
4568         /// NULL if compilation failed
4569         IDirect3DVertexShader9 *vertexshader;
4570         IDirect3DPixelShader9 *pixelshader;
4571 }
4572 r_hlsl_permutation_t;
4573
4574 typedef enum D3DVSREGISTER_e
4575 {
4576         D3DVSREGISTER_TexMatrix = 0, // float4x4
4577         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581         D3DVSREGISTER_ModelToLight = 20, // float4x4
4582         D3DVSREGISTER_EyePosition = 24,
4583         D3DVSREGISTER_FogPlane = 25,
4584         D3DVSREGISTER_LightDir = 26,
4585         D3DVSREGISTER_LightPosition = 27,
4586 }
4587 D3DVSREGISTER_t;
4588
4589 typedef enum D3DPSREGISTER_e
4590 {
4591         D3DPSREGISTER_Alpha = 0,
4592         D3DPSREGISTER_BloomBlur_Parameters = 1,
4593         D3DPSREGISTER_ClientTime = 2,
4594         D3DPSREGISTER_Color_Ambient = 3,
4595         D3DPSREGISTER_Color_Diffuse = 4,
4596         D3DPSREGISTER_Color_Specular = 5,
4597         D3DPSREGISTER_Color_Glow = 6,
4598         D3DPSREGISTER_Color_Pants = 7,
4599         D3DPSREGISTER_Color_Shirt = 8,
4600         D3DPSREGISTER_DeferredColor_Ambient = 9,
4601         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602         D3DPSREGISTER_DeferredColor_Specular = 11,
4603         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604         D3DPSREGISTER_DeferredMod_Specular = 13,
4605         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606         D3DPSREGISTER_EyePosition = 15, // unused
4607         D3DPSREGISTER_FogColor = 16,
4608         D3DPSREGISTER_FogHeightFade = 17,
4609         D3DPSREGISTER_FogPlane = 18,
4610         D3DPSREGISTER_FogPlaneViewDist = 19,
4611         D3DPSREGISTER_FogRangeRecip = 20,
4612         D3DPSREGISTER_LightColor = 21,
4613         D3DPSREGISTER_LightDir = 22, // unused
4614         D3DPSREGISTER_LightPosition = 23,
4615         D3DPSREGISTER_OffsetMapping_Scale = 24,
4616         D3DPSREGISTER_PixelSize = 25,
4617         D3DPSREGISTER_ReflectColor = 26,
4618         D3DPSREGISTER_ReflectFactor = 27,
4619         D3DPSREGISTER_ReflectOffset = 28,
4620         D3DPSREGISTER_RefractColor = 29,
4621         D3DPSREGISTER_Saturation = 30,
4622         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624         D3DPSREGISTER_ScreenToDepth = 33,
4625         D3DPSREGISTER_ShadowMap_Parameters = 34,
4626         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627         D3DPSREGISTER_SpecularPower = 36,
4628         D3DPSREGISTER_UserVec1 = 37,
4629         D3DPSREGISTER_UserVec2 = 38,
4630         D3DPSREGISTER_UserVec3 = 39,
4631         D3DPSREGISTER_UserVec4 = 40,
4632         D3DPSREGISTER_ViewTintColor = 41,
4633         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634         D3DPSREGISTER_BloomColorSubtract = 43,
4635         D3DPSREGISTER_ViewToLight = 44, // float4x4
4636         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4637         // next at 52
4638 }
4639 D3DPSREGISTER_t;
4640
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4647
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4649 {
4650         //unsigned int hashdepth = 0;
4651         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652         r_hlsl_permutation_t *p;
4653         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4654         {
4655                 if (p->mode == mode && p->permutation == permutation)
4656                 {
4657                         //if (hashdepth > 10)
4658                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4659                         return p;
4660                 }
4661                 //hashdepth++;
4662         }
4663         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4664         p->mode = mode;
4665         p->permutation = permutation;
4666         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667         r_hlsl_permutationhash[mode][hashindex] = p;
4668         //if (hashdepth > 10)
4669         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4670         return p;
4671 }
4672
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4674 {
4675         char *shaderstring;
4676         if (!filename || !filename[0])
4677                 return NULL;
4678         if (!strcmp(filename, "hlsl/default.hlsl"))
4679         {
4680                 if (!hlslshaderstring)
4681                 {
4682                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683                         if (hlslshaderstring)
4684                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4685                         else
4686                                 hlslshaderstring = (char *)builtincgshaderstring;
4687                 }
4688                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690                 return shaderstring;
4691         }
4692         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4693         if (shaderstring)
4694         {
4695                 if (printfromdisknotice)
4696                         Con_DPrintf("from disk %s... ", filename);
4697                 return shaderstring;
4698         }
4699         return shaderstring;
4700 }
4701
4702 #include <d3dx9.h>
4703 //#include <d3dx9shader.h>
4704 //#include <d3dx9mesh.h>
4705
4706 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4707 {
4708         DWORD *vsbin = NULL;
4709         DWORD *psbin = NULL;
4710         fs_offset_t vsbinsize;
4711         fs_offset_t psbinsize;
4712 //      IDirect3DVertexShader9 *vs = NULL;
4713 //      IDirect3DPixelShader9 *ps = NULL;
4714         ID3DXBuffer *vslog = NULL;
4715         ID3DXBuffer *vsbuffer = NULL;
4716         ID3DXConstantTable *vsconstanttable = NULL;
4717         ID3DXBuffer *pslog = NULL;
4718         ID3DXBuffer *psbuffer = NULL;
4719         ID3DXConstantTable *psconstanttable = NULL;
4720         int vsresult = 0;
4721         int psresult = 0;
4722         char temp[MAX_INPUTLINE];
4723         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4724         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4725         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4726         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4727         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4728         if ((!vsbin && vertstring) || (!psbin && fragstring))
4729         {
4730                 const char* dllnames_d3dx9 [] =
4731                 {
4732                         "d3dx9_43.dll",
4733                         "d3dx9_42.dll",
4734                         "d3dx9_41.dll",
4735                         "d3dx9_40.dll",
4736                         "d3dx9_39.dll",
4737                         "d3dx9_38.dll",
4738                         "d3dx9_37.dll",
4739                         "d3dx9_36.dll",
4740                         "d3dx9_35.dll",
4741                         "d3dx9_34.dll",
4742                         "d3dx9_33.dll",
4743                         "d3dx9_32.dll",
4744                         "d3dx9_31.dll",
4745                         "d3dx9_30.dll",
4746                         "d3dx9_29.dll",
4747                         "d3dx9_28.dll",
4748                         "d3dx9_27.dll",
4749                         "d3dx9_26.dll",
4750                         "d3dx9_25.dll",
4751                         "d3dx9_24.dll",
4752                         NULL
4753                 };
4754                 dllhandle_t d3dx9_dll = NULL;
4755                 HRESULT WINAPI (*qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4756                 dllfunction_t d3dx9_dllfuncs[] =
4757                 {
4758                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4759                         {NULL, NULL}
4760                 };
4761                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4762                 {
4763                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4764                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4765                         if (vertstring && vertstring[0])
4766                         {
4767                                 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
4768                                 if (vsbuffer)
4769                                 {
4770                                         vsbinsize = vsbuffer->GetBufferSize();
4771                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4772                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4773                                         vsbuffer->Release();
4774                                 }
4775                                 if (vslog)
4776                                 {
4777                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4778                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4779                                         vslog->Release();
4780                                 }
4781                         }
4782                         if (fragstring && fragstring[0])
4783                         {
4784                                 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
4785                                 if (psbuffer)
4786                                 {
4787                                         psbinsize = psbuffer->GetBufferSize();
4788                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4789                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4790                                         psbuffer->Release();
4791                                 }
4792                                 if (pslog)
4793                                 {
4794                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4795                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4796                                         pslog->Release();
4797                                 }
4798                         }
4799                         Sys_UnloadLibrary(&d3dx9_dll);
4800                 }
4801                 else
4802                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4803         }
4804         if (vsbin)
4805         {
4806                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4807                 if (FAILED(vsresult))
4808                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4809         }
4810         if (psbin)
4811         {
4812                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4813                 if (FAILED(psresult))
4814                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4815         }
4816         // free the shader data
4817         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4818         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4819 }
4820
4821 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4822 {
4823         int i;
4824         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4825         int vertstrings_count = 0, vertstring_length = 0;
4826         int geomstrings_count = 0, geomstring_length = 0;
4827         int fragstrings_count = 0, fragstring_length = 0;
4828         char *t;
4829         char *vertexstring, *geometrystring, *fragmentstring;
4830         char *vertstring, *geomstring, *fragstring;
4831         const char *vertstrings_list[32+3];
4832         const char *geomstrings_list[32+3];
4833         const char *fragstrings_list[32+3];
4834         char permutationname[256];
4835         char cachename[256];
4836
4837         if (p->compiled)
4838                 return;
4839         p->compiled = true;
4840         p->vertexshader = NULL;
4841         p->pixelshader = NULL;
4842
4843         permutationname[0] = 0;
4844         cachename[0] = 0;
4845         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4846         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4847         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4848
4849         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4850         strlcat(cachename, "hlsl/", sizeof(cachename));
4851
4852         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4853         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4854         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4855         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4856
4857         // the first pretext is which type of shader to compile as
4858         // (later these will all be bound together as a program object)
4859         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4860         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4861         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4862
4863         // the second pretext is the mode (for example a light source)
4864         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4865         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4866         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4867         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4868         strlcat(cachename, modeinfo->name, sizeof(cachename));
4869
4870         // now add all the permutation pretexts
4871         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4872         {
4873                 if (permutation & (1<<i))
4874                 {
4875                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4876                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4877                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4878                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4879                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4880                 }
4881                 else
4882                 {
4883                         // keep line numbers correct
4884                         vertstrings_list[vertstrings_count++] = "\n";
4885                         geomstrings_list[geomstrings_count++] = "\n";
4886                         fragstrings_list[fragstrings_count++] = "\n";
4887                 }
4888         }
4889
4890         // replace spaces in the cachename with _ characters
4891         for (i = 0;cachename[i];i++)
4892                 if (cachename[i] == ' ')
4893                         cachename[i] = '_';
4894
4895         // now append the shader text itself
4896         vertstrings_list[vertstrings_count++] = vertexstring;
4897         geomstrings_list[geomstrings_count++] = geometrystring;
4898         fragstrings_list[fragstrings_count++] = fragmentstring;
4899
4900         // if any sources were NULL, clear the respective list
4901         if (!vertexstring)
4902                 vertstrings_count = 0;
4903         if (!geometrystring)
4904                 geomstrings_count = 0;
4905         if (!fragmentstring)
4906                 fragstrings_count = 0;
4907
4908         vertstring_length = 0;
4909         for (i = 0;i < vertstrings_count;i++)
4910                 vertstring_length += strlen(vertstrings_list[i]);
4911         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4912         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4913                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4914
4915         geomstring_length = 0;
4916         for (i = 0;i < geomstrings_count;i++)
4917                 geomstring_length += strlen(geomstrings_list[i]);
4918         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4919         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4920                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4921
4922         fragstring_length = 0;
4923         for (i = 0;i < fragstrings_count;i++)
4924                 fragstring_length += strlen(fragstrings_list[i]);
4925         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4926         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4927                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4928
4929         // try to load the cached shader, or generate one
4930         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4931
4932         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4933                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4934         else
4935                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4936
4937         // free the strings
4938         if (vertstring)
4939                 Mem_Free(vertstring);
4940         if (geomstring)
4941                 Mem_Free(geomstring);
4942         if (fragstring)
4943                 Mem_Free(fragstring);
4944         if (vertexstring)
4945                 Mem_Free(vertexstring);
4946         if (geometrystring)
4947                 Mem_Free(geometrystring);
4948         if (fragmentstring)
4949                 Mem_Free(fragmentstring);
4950 }
4951
4952 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4953 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4954 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);}
4955 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);}
4956 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);}
4957 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);}
4958
4959 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4960 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4961 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);}
4962 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);}
4963 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);}
4964 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);}
4965
4966 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4967 {
4968         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4969         if (r_hlsl_permutation != perm)
4970         {
4971                 r_hlsl_permutation = perm;
4972                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4973                 {
4974                         if (!r_hlsl_permutation->compiled)
4975                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4976                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4977                         {
4978                                 // remove features until we find a valid permutation
4979                                 int i;
4980                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4981                                 {
4982                                         // reduce i more quickly whenever it would not remove any bits
4983                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4984                                         if (!(permutation & j))
4985                                                 continue;
4986                                         permutation -= j;
4987                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4988                                         if (!r_hlsl_permutation->compiled)
4989                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4990                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4991                                                 break;
4992                                 }
4993                                 if (i >= SHADERPERMUTATION_COUNT)
4994                                 {
4995                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4996                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4997                                         return; // no bit left to clear, entire mode is broken
4998                                 }
4999                         }
5000                 }
5001                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5002                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5003         }
5004         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5005         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5006         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5007 }
5008 #endif
5009
5010 void R_GLSL_Restart_f(void)
5011 {
5012         unsigned int i, limit;
5013         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5014                 Mem_Free(glslshaderstring);
5015         glslshaderstring = NULL;
5016         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5017                 Mem_Free(cgshaderstring);
5018         cgshaderstring = NULL;
5019         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5020                 Mem_Free(hlslshaderstring);
5021         hlslshaderstring = NULL;
5022         switch(vid.renderpath)
5023         {
5024         case RENDERPATH_D3D9:
5025 #ifdef SUPPORTD3D
5026                 {
5027                         r_hlsl_permutation_t *p;
5028                         r_hlsl_permutation = NULL;
5029 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5030 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5031 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5032 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5033                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5034                         for (i = 0;i < limit;i++)
5035                         {
5036                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5037                                 {
5038                                         if (p->vertexshader)
5039                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5040                                         if (p->pixelshader)
5041                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5042                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5043                                 }
5044                         }
5045                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5046                 }
5047 #endif
5048                 break;
5049         case RENDERPATH_D3D10:
5050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5051                 break;
5052         case RENDERPATH_D3D11:
5053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5054                 break;
5055         case RENDERPATH_GL20:
5056                 {
5057                         r_glsl_permutation_t *p;
5058                         r_glsl_permutation = NULL;
5059                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5060                         for (i = 0;i < limit;i++)
5061                         {
5062                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5063                                 {
5064                                         GL_Backend_FreeProgram(p->program);
5065                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5066                                 }
5067                         }
5068                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5069                 }
5070                 break;
5071         case RENDERPATH_CGGL:
5072 #ifdef SUPPORTCG
5073                 {
5074                         r_cg_permutation_t *p;
5075                         r_cg_permutation = NULL;
5076                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5077                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5078                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5079                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5080                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5081                         for (i = 0;i < limit;i++)
5082                         {
5083                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5084                                 {
5085                                         if (p->vprogram)
5086                                                 cgDestroyProgram(p->vprogram);
5087                                         if (p->fprogram)
5088                                                 cgDestroyProgram(p->fprogram);
5089                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5090                                 }
5091                         }
5092                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5093                 }
5094 #endif
5095                 break;
5096         case RENDERPATH_GL13:
5097         case RENDERPATH_GL11:
5098                 break;
5099         }
5100 }
5101
5102 void R_GLSL_DumpShader_f(void)
5103 {
5104         int i;
5105         qfile_t *file;
5106
5107         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5108         if (file)
5109         {
5110                 FS_Print(file, "/* The engine may define the following macros:\n");
5111                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5112                 for (i = 0;i < SHADERMODE_COUNT;i++)
5113                         FS_Print(file, glslshadermodeinfo[i].pretext);
5114                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5115                         FS_Print(file, shaderpermutationinfo[i].pretext);
5116                 FS_Print(file, "*/\n");
5117                 FS_Print(file, builtinshaderstring);
5118                 FS_Close(file);
5119                 Con_Printf("glsl/default.glsl written\n");
5120         }
5121         else
5122                 Con_Printf("failed to write to glsl/default.glsl\n");
5123
5124 #ifdef SUPPORTCG
5125         file = FS_OpenRealFile("cg/default.cg", "w", false);
5126         if (file)
5127         {
5128                 FS_Print(file, "/* The engine may define the following macros:\n");
5129                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5130                 for (i = 0;i < SHADERMODE_COUNT;i++)
5131                         FS_Print(file, cgshadermodeinfo[i].pretext);
5132                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5133                         FS_Print(file, shaderpermutationinfo[i].pretext);
5134                 FS_Print(file, "*/\n");
5135                 FS_Print(file, builtincgshaderstring);
5136                 FS_Close(file);
5137                 Con_Printf("cg/default.cg written\n");
5138         }
5139         else
5140                 Con_Printf("failed to write to cg/default.cg\n");
5141 #endif
5142
5143 #ifdef SUPPORTD3D
5144         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5145         if (file)
5146         {
5147                 FS_Print(file, "/* The engine may define the following macros:\n");
5148                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5149                 for (i = 0;i < SHADERMODE_COUNT;i++)
5150                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5151                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5152                         FS_Print(file, shaderpermutationinfo[i].pretext);
5153                 FS_Print(file, "*/\n");
5154                 FS_Print(file, builtincgshaderstring);
5155                 FS_Close(file);
5156                 Con_Printf("hlsl/default.hlsl written\n");
5157         }
5158         else
5159                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5160 #endif
5161 }
5162
5163 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5164 {
5165         if (!second)
5166                 texturemode = GL_MODULATE;
5167         switch (vid.renderpath)
5168         {
5169         case RENDERPATH_D3D9:
5170 #ifdef SUPPORTD3D
5171                 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))));
5172                 R_Mesh_TexBind(GL20TU_FIRST , first );
5173                 R_Mesh_TexBind(GL20TU_SECOND, second);
5174 #endif
5175                 break;
5176         case RENDERPATH_D3D10:
5177                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5178                 break;
5179         case RENDERPATH_D3D11:
5180                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5181                 break;
5182         case RENDERPATH_GL20:
5183                 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))));
5184                 R_Mesh_TexBind(GL20TU_FIRST , first );
5185                 R_Mesh_TexBind(GL20TU_SECOND, second);
5186                 break;
5187         case RENDERPATH_CGGL:
5188 #ifdef SUPPORTCG
5189                 CHECKCGERROR
5190                 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))));
5191                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5192                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5193 #endif
5194                 break;
5195         case RENDERPATH_GL13:
5196                 R_Mesh_TexBind(0, first );
5197                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5198                 R_Mesh_TexBind(1, second);
5199                 if (second)
5200                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5201                 break;
5202         case RENDERPATH_GL11:
5203                 R_Mesh_TexBind(0, first );
5204                 break;
5205         }
5206 }
5207
5208 void R_SetupShader_DepthOrShadow(void)
5209 {
5210         switch (vid.renderpath)
5211         {
5212         case RENDERPATH_D3D9:
5213 #ifdef SUPPORTD3D
5214                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5215 #endif
5216                 break;
5217         case RENDERPATH_D3D10:
5218                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5219                 break;
5220         case RENDERPATH_D3D11:
5221                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5222                 break;
5223         case RENDERPATH_GL20:
5224                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5225                 break;
5226         case RENDERPATH_CGGL:
5227 #ifdef SUPPORTCG
5228                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5229 #endif
5230                 break;
5231         case RENDERPATH_GL13:
5232                 R_Mesh_TexBind(0, 0);
5233                 R_Mesh_TexBind(1, 0);
5234                 break;
5235         case RENDERPATH_GL11:
5236                 R_Mesh_TexBind(0, 0);
5237                 break;
5238         }
5239 }
5240
5241 void R_SetupShader_ShowDepth(void)
5242 {
5243         switch (vid.renderpath)
5244         {
5245         case RENDERPATH_D3D9:
5246 #ifdef SUPPORTHLSL
5247                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5248 #endif
5249                 break;
5250         case RENDERPATH_D3D10:
5251                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5252                 break;
5253         case RENDERPATH_D3D11:
5254                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5255                 break;
5256         case RENDERPATH_GL20:
5257                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5258                 break;
5259         case RENDERPATH_CGGL:
5260 #ifdef SUPPORTCG
5261                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5262 #endif
5263                 break;
5264         case RENDERPATH_GL13:
5265                 break;
5266         case RENDERPATH_GL11:
5267                 break;
5268         }
5269 }
5270
5271 extern qboolean r_shadow_usingdeferredprepass;
5272 extern cvar_t r_shadow_deferred_8bitrange;
5273 extern rtexture_t *r_shadow_attenuationgradienttexture;
5274 extern rtexture_t *r_shadow_attenuation2dtexture;
5275 extern rtexture_t *r_shadow_attenuation3dtexture;
5276 extern qboolean r_shadow_usingshadowmaprect;
5277 extern qboolean r_shadow_usingshadowmapcube;
5278 extern qboolean r_shadow_usingshadowmap2d;
5279 extern qboolean r_shadow_usingshadowmaportho;
5280 extern float r_shadow_shadowmap_texturescale[2];
5281 extern float r_shadow_shadowmap_parameters[4];
5282 extern qboolean r_shadow_shadowmapvsdct;
5283 extern qboolean r_shadow_shadowmapsampler;
5284 extern int r_shadow_shadowmappcf;
5285 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5286 extern rtexture_t *r_shadow_shadowmap2dtexture;
5287 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5288 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5289 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5290 extern matrix4x4_t r_shadow_shadowmapmatrix;
5291 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5292 extern int r_shadow_prepass_width;
5293 extern int r_shadow_prepass_height;
5294 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5295 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5296 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5297 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5298 extern cvar_t gl_mesh_separatearrays;
5299 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5300 {
5301         // a blendfunc allows colormod if:
5302         // a) it can never keep the destination pixel invariant, or
5303         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5304         // this is to prevent unintended side effects from colormod
5305
5306         // in formulas:
5307         // IF there is a (s, sa) for which for all (d, da),
5308         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5309         // THEN, for this (s, sa) and all (colormod, d, da):
5310         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5311         // OBVIOUSLY, this means that
5312         //   s*colormod * src(s*colormod, d, sa, da) = 0
5313         //   dst(s*colormod, d, sa, da)              = 1
5314
5315         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5316
5317         // main condition to leave dst color invariant:
5318         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5319         //   src == GL_ZERO:
5320         //     s * 0 + d * dst(s, d, sa, da) == d
5321         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5322         //       => colormod is a problem for GL_SRC_COLOR only
5323         //   src == GL_ONE:
5324         //     s + d * dst(s, d, sa, da) == d
5325         //       => s == 0
5326         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5327         //       => colormod is never problematic for these
5328         //   src == GL_SRC_COLOR:
5329         //     s*s + d * dst(s, d, sa, da) == d
5330         //       => s == 0
5331         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5332         //       => colormod is never problematic for these
5333         //   src == GL_ONE_MINUS_SRC_COLOR:
5334         //     s*(1-s) + d * dst(s, d, sa, da) == d
5335         //       => s == 0 or s == 1
5336         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5337         //       => colormod is a problem for GL_SRC_COLOR only
5338         //   src == GL_DST_COLOR
5339         //     s*d + d * dst(s, d, sa, da) == d
5340         //       => s == 1
5341         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5342         //       => colormod is always a problem
5343         //     or
5344         //       => s == 0
5345         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5346         //       => colormod is never problematic for these
5347         //       => BUT, we do not know s! We must assume it is problematic
5348         //       then... except in GL_ONE case, where we know all invariant
5349         //       cases are fine
5350         //   src == GL_ONE_MINUS_DST_COLOR
5351         //     s*(1-d) + d * dst(s, d, sa, da) == d
5352         //       => s == 0 (1-d is impossible to handle for our desired result)
5353         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5354         //       => colormod is never problematic for these
5355         //   src == GL_SRC_ALPHA
5356         //     s*sa + d * dst(s, d, sa, da) == d
5357         //       => s == 0, or sa == 0
5358         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5359         //       => colormod breaks in the case GL_SRC_COLOR only
5360         //   src == GL_ONE_MINUS_SRC_ALPHA
5361         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5362         //       => s == 0, or sa == 1
5363         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5364         //       => colormod breaks in the case GL_SRC_COLOR only
5365         //   src == GL_DST_ALPHA
5366         //     s*da + d * dst(s, d, sa, da) == d
5367         //       => s == 0
5368         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5369         //       => colormod is never problematic for these
5370
5371         switch(src)
5372         {
5373                 case GL_ZERO:
5374                 case GL_ONE_MINUS_SRC_COLOR:
5375                 case GL_SRC_ALPHA:
5376                 case GL_ONE_MINUS_SRC_ALPHA:
5377                         if(dst == GL_SRC_COLOR)
5378                                 return false;
5379                         return true;
5380                 case GL_ONE:
5381                 case GL_SRC_COLOR:
5382                 case GL_ONE_MINUS_DST_COLOR:
5383                 case GL_DST_ALPHA:
5384                 case GL_ONE_MINUS_DST_ALPHA:
5385                         return true;
5386                 case GL_DST_COLOR:
5387                         if(dst == GL_ONE)
5388                                 return true;
5389                         return false;
5390                 default:
5391                         return false;
5392         }
5393 }
5394 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)
5395 {
5396         // select a permutation of the lighting shader appropriate to this
5397         // combination of texture, entity, light source, and fogging, only use the
5398         // minimum features necessary to avoid wasting rendering time in the
5399         // fragment shader on features that are not being used
5400         unsigned int permutation = 0;
5401         unsigned int mode = 0;
5402         qboolean allow_colormod;
5403         static float dummy_colormod[3] = {1, 1, 1};
5404         float *colormod = rsurface.colormod;
5405         float m16f[16];
5406         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5407         if (rsurfacepass == RSURFPASS_BACKGROUND)
5408         {
5409                 // distorted background
5410                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5411                         mode = SHADERMODE_WATER;
5412                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5413                         mode = SHADERMODE_REFRACTION;
5414                 else
5415                 {
5416                         mode = SHADERMODE_GENERIC;
5417                         permutation |= SHADERPERMUTATION_DIFFUSE;
5418                 }
5419                 GL_AlphaTest(false);
5420                 GL_BlendFunc(GL_ONE, GL_ZERO);
5421                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5422         }
5423         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5424         {
5425                 if (r_glsl_offsetmapping.integer)
5426                 {
5427                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5428                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5429                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5430                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5431                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5432                         {
5433                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5434                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5435                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436                         }
5437                 }
5438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5439                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5441                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5442                 // normalmap (deferred prepass), may use alpha test on diffuse
5443                 mode = SHADERMODE_DEFERREDGEOMETRY;
5444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5446                 GL_AlphaTest(false);
5447                 GL_BlendFunc(GL_ONE, GL_ZERO);
5448                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5449         }
5450         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5451         {
5452                 if (r_glsl_offsetmapping.integer)
5453                 {
5454                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5456                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5457                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5458                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5459                         {
5460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5461                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5462                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5463                         }
5464                 }
5465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467                 // light source
5468                 mode = SHADERMODE_LIGHTSOURCE;
5469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5470                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5471                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5472                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5473                 if (diffusescale > 0)
5474                         permutation |= SHADERPERMUTATION_DIFFUSE;
5475                 if (specularscale > 0)
5476                 {
5477                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5478                         if (r_shadow_glossexact.integer)
5479                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5480                 }
5481                 if (r_refdef.fogenabled)
5482                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5483                 if (rsurface.texture->colormapping)
5484                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5485                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5486                 {
5487                         if (r_shadow_usingshadowmaprect)
5488                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5489                         if (r_shadow_usingshadowmap2d)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5491                         if (r_shadow_usingshadowmapcube)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5493                         else if(r_shadow_shadowmapvsdct)
5494                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5495
5496                         if (r_shadow_shadowmapsampler)
5497                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5498                         if (r_shadow_shadowmappcf > 1)
5499                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5500                         else if (r_shadow_shadowmappcf)
5501                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5502                 }
5503                 if (rsurface.texture->reflectmasktexture)
5504                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5505                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5506                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5507                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5508         }
5509         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5510         {
5511                 if (r_glsl_offsetmapping.integer)
5512                 {
5513                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5514                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5515                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5516                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5517                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5518                         {
5519                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5520                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5521                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5522                         }
5523                 }
5524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5525                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5526                 // unshaded geometry (fullbright or ambient model lighting)
5527                 mode = SHADERMODE_FLATCOLOR;
5528                 ambientscale = diffusescale = specularscale = 0;
5529                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530                         permutation |= SHADERPERMUTATION_GLOW;
5531                 if (r_refdef.fogenabled)
5532                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5533                 if (rsurface.texture->colormapping)
5534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5535                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5536                 {
5537                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5538                         if (r_shadow_usingshadowmaprect)
5539                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5540                         if (r_shadow_usingshadowmap2d)
5541                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5542
5543                         if (r_shadow_shadowmapsampler)
5544                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545                         if (r_shadow_shadowmappcf > 1)
5546                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547                         else if (r_shadow_shadowmappcf)
5548                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551                         permutation |= SHADERPERMUTATION_REFLECTION;
5552                 if (rsurface.texture->reflectmasktexture)
5553                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5554                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5555                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5556                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5557         }
5558         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5559         {
5560                 if (r_glsl_offsetmapping.integer)
5561                 {
5562                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5563                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5564                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5566                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5567                         {
5568                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5569                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5570                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5571                         }
5572                 }
5573                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5574                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5575                 // directional model lighting
5576                 mode = SHADERMODE_LIGHTDIRECTION;
5577                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5578                         permutation |= SHADERPERMUTATION_GLOW;
5579                 permutation |= SHADERPERMUTATION_DIFFUSE;
5580                 if (specularscale > 0)
5581                 {
5582                         permutation |= SHADERPERMUTATION_SPECULAR;
5583                         if (r_shadow_glossexact.integer)
5584                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5585                 }
5586                 if (r_refdef.fogenabled)
5587                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5588                 if (rsurface.texture->colormapping)
5589                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5590                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5591                 {
5592                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5593                         if (r_shadow_usingshadowmaprect)
5594                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5595                         if (r_shadow_usingshadowmap2d)
5596                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5597
5598                         if (r_shadow_shadowmapsampler)
5599                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5600                         if (r_shadow_shadowmappcf > 1)
5601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5602                         else if (r_shadow_shadowmappcf)
5603                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5604                 }
5605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5606                         permutation |= SHADERPERMUTATION_REFLECTION;
5607                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5608                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5609                 if (rsurface.texture->reflectmasktexture)
5610                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5611                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5612                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5613                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5614         }
5615         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5616         {
5617                 if (r_glsl_offsetmapping.integer)
5618                 {
5619                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5620                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5621                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5622                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5623                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5624                         {
5625                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5626                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5627                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5628                         }
5629                 }
5630                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5631                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5632                 // ambient model lighting
5633                 mode = SHADERMODE_LIGHTDIRECTION;
5634                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5635                         permutation |= SHADERPERMUTATION_GLOW;
5636                 if (r_refdef.fogenabled)
5637                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5638                 if (rsurface.texture->colormapping)
5639                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5640                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5641                 {
5642                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5643                         if (r_shadow_usingshadowmaprect)
5644                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5645                         if (r_shadow_usingshadowmap2d)
5646                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5647
5648                         if (r_shadow_shadowmapsampler)
5649                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5650                         if (r_shadow_shadowmappcf > 1)
5651                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5652                         else if (r_shadow_shadowmappcf)
5653                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5654                 }
5655                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5656                         permutation |= SHADERPERMUTATION_REFLECTION;
5657                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5658                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5659                 if (rsurface.texture->reflectmasktexture)
5660                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5661                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5662                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5663                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664         }
5665         else
5666         {
5667                 if (r_glsl_offsetmapping.integer)
5668                 {
5669                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5670                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5671                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5672                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5673                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5674                         {
5675                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5676                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5677                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5678                         }
5679                 }
5680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5682                 // lightmapped wall
5683                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5684                         permutation |= SHADERPERMUTATION_GLOW;
5685                 if (r_refdef.fogenabled)
5686                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5687                 if (rsurface.texture->colormapping)
5688                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5689                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5690                 {
5691                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5692                         if (r_shadow_usingshadowmaprect)
5693                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5694                         if (r_shadow_usingshadowmap2d)
5695                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5696
5697                         if (r_shadow_shadowmapsampler)
5698                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5699                         if (r_shadow_shadowmappcf > 1)
5700                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5701                         else if (r_shadow_shadowmappcf)
5702                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5703                 }
5704                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5705                         permutation |= SHADERPERMUTATION_REFLECTION;
5706                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5707                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5708                 if (rsurface.texture->reflectmasktexture)
5709                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5710                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5711                 {
5712                         // deluxemapping (light direction texture)
5713                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5714                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5715                         else
5716                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5717                         permutation |= SHADERPERMUTATION_DIFFUSE;
5718                         if (specularscale > 0)
5719                         {
5720                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5721                                 if (r_shadow_glossexact.integer)
5722                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5723                         }
5724                 }
5725                 else if (r_glsl_deluxemapping.integer >= 2)
5726                 {
5727                         // fake deluxemapping (uniform light direction in tangentspace)
5728                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5729                         permutation |= SHADERPERMUTATION_DIFFUSE;
5730                         if (specularscale > 0)
5731                         {
5732                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5733                                 if (r_shadow_glossexact.integer)
5734                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5735                         }
5736                 }
5737                 else if (rsurface.uselightmaptexture)
5738                 {
5739                         // ordinary lightmapping (q1bsp, q3bsp)
5740                         mode = SHADERMODE_LIGHTMAP;
5741                 }
5742                 else
5743                 {
5744                         // ordinary vertex coloring (q3bsp)
5745                         mode = SHADERMODE_VERTEXCOLOR;
5746                 }
5747                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5748                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5749                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5750         }
5751         if(!allow_colormod)
5752                 colormod = dummy_colormod;
5753         switch(vid.renderpath)
5754         {
5755         case RENDERPATH_D3D9:
5756 #ifdef SUPPORTD3D
5757                 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);
5758                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5759                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5760                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5761                 if (mode == SHADERMODE_LIGHTSOURCE)
5762                 {
5763                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5764                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5765                 }
5766                 else
5767                 {
5768                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5769                         {
5770                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5771                         }
5772                 }
5773                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5774                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5775                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5776                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5777                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5778
5779                 if (mode == SHADERMODE_LIGHTSOURCE)
5780                 {
5781                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5782                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5783                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5784                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5785                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5786
5787                         // additive passes are only darkened by fog, not tinted
5788                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5790                 }
5791                 else
5792                 {
5793                         if (mode == SHADERMODE_FLATCOLOR)
5794                         {
5795                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5796                         }
5797                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5798                         {
5799                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5800                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5801                                 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);
5802                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5803                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5804                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5805                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5806                         }
5807                         else
5808                         {
5809                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5810                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5811                                 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);
5812                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5813                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5814                         }
5815                         // additive passes are only darkened by fog, not tinted
5816                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5817                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5818                         else
5819                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5820                         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);
5821                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5822                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5823                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5824                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5825                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5826                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5827                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5828                 }
5829                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5830                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5831                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5832                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5833                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5834                 if (rsurface.texture->pantstexture)
5835                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5836                 else
5837                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5838                 if (rsurface.texture->shirttexture)
5839                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5840                 else
5841                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5842                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5843                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5844                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5845                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5846                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5847                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5848                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5849
5850                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5851                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5852                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5853                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5854                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5855                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5856                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5857                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5858                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5859                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5860                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5861                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5862                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5863                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5864                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5865                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5866                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5867                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5868                 {
5869                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5870                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5871                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5872                 }
5873                 else
5874                 {
5875                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5876                 }
5877 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5878 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5879                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5880                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5881                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5882                 {
5883                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5884                         if (rsurface.rtlight)
5885                         {
5886                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5887                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5888                         }
5889                 }
5890 #endif
5891                 break;
5892         case RENDERPATH_D3D10:
5893                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5894                 break;
5895         case RENDERPATH_D3D11:
5896                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5897                 break;
5898         case RENDERPATH_GL20:
5899                 if (gl_mesh_separatearrays.integer)
5900                 {
5901                         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);
5902                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5903                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5904                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5905                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5906                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5907                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5908                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5909                 }
5910                 else
5911                 {
5912                         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);
5913                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5914                 }
5915                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5916                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5917                 if (mode == SHADERMODE_LIGHTSOURCE)
5918                 {
5919                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5920                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5921                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5922                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5923                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5924                         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);
5925         
5926                         // additive passes are only darkened by fog, not tinted
5927                         if (r_glsl_permutation->loc_FogColor >= 0)
5928                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5929                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5930                 }
5931                 else
5932                 {
5933                         if (mode == SHADERMODE_FLATCOLOR)
5934                         {
5935                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5936                         }
5937                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5938                         {
5939                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5940                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5941                                 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);
5942                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5943                                 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);
5944                                 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]);
5945                                 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]);
5946                         }
5947                         else
5948                         {
5949                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5950                                 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]);
5951                                 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);
5952                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5953                                 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);
5954                         }
5955                         // additive passes are only darkened by fog, not tinted
5956                         if (r_glsl_permutation->loc_FogColor >= 0)
5957                         {
5958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5959                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5960                                 else
5961                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5962                         }
5963                         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);
5964                         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]);
5965                         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]);
5966                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5967                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5968                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5969                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5970                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5971                 }
5972                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5973                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5974                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5975                 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]);
5976                 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]);
5977
5978                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5979                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5980                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5981                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5982                 {
5983                         if (rsurface.texture->pantstexture)
5984                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5985                         else
5986                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5987                 }
5988                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5989                 {
5990                         if (rsurface.texture->shirttexture)
5991                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5992                         else
5993                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5994                 }
5995                 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]);
5996                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5997                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5998                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5999                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6000                 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]);
6001                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6002
6003         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6004         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6005         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6006                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6007                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6008                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6009                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6010                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6011                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6012                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6013                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6014                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6015                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6016                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6017                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6018                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6019                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6020                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6021                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6022                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6023                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6024                 {
6025                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6026                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6027                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6028                 }
6029                 else
6030                 {
6031                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6032                 }
6033 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6034 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6035                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6036                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6037                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6038                 {
6039                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6040                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
6041                         if (rsurface.rtlight)
6042                         {
6043                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6044                                 if (r_shadow_usingshadowmapcube)
6045                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6046                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6047                         }
6048                 }
6049                 CHECKGLERROR
6050                 break;
6051         case RENDERPATH_CGGL:
6052 #ifdef SUPPORTCG
6053                 if (gl_mesh_separatearrays.integer)
6054                 {
6055                         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);
6056                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6057                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6058                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6059                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6060                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6061                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6062                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6063                 }
6064                 else
6065                 {
6066                         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);
6067                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6068                 }
6069                 R_SetupShader_SetPermutationCG(mode, permutation);
6070                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6071                 if (mode == SHADERMODE_LIGHTSOURCE)
6072                 {
6073                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6074                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6075                 }
6076                 else
6077                 {
6078                         if (mode == SHADERMODE_LIGHTDIRECTION)
6079                         {
6080                                 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
6081                         }
6082                 }
6083                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6084                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6085                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6086                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6087                 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
6088                 CHECKGLERROR
6089
6090                 if (mode == SHADERMODE_LIGHTSOURCE)
6091                 {
6092                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6093                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6094                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6095                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6096                         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
6097
6098                         // additive passes are only darkened by fog, not tinted
6099                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6100                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6101                 }
6102                 else
6103                 {
6104                         if (mode == SHADERMODE_FLATCOLOR)
6105                         {
6106                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6107                         }
6108                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6109                         {
6110                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6111                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6112                                 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
6113                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6114                                 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
6115                                 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
6116                                 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
6117                         }
6118                         else
6119                         {
6120                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6121                                 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
6122                                 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
6123                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6124                                 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
6125                         }
6126                         // additive passes are only darkened by fog, not tinted
6127                         if (r_cg_permutation->fp_FogColor)
6128                         {
6129                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6130                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6131                                 else
6132                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6133                                 CHECKCGERROR
6134                         }
6135                         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
6136                         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
6137                         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
6138                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6139                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6140                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6141                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6142                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6143                 }
6144                 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
6145                 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
6146                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6148                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6149                 if (r_cg_permutation->fp_Color_Pants)
6150                 {
6151                         if (rsurface.texture->pantstexture)
6152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6153                         else
6154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6155                         CHECKCGERROR
6156                 }
6157                 if (r_cg_permutation->fp_Color_Shirt)
6158                 {
6159                         if (rsurface.texture->shirttexture)
6160                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6161                         else
6162                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6163                         CHECKCGERROR
6164                 }
6165                 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
6166                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6167                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6168                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6169                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6170                 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
6171                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6172
6173         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6174         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6175         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6176                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6177                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6178                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6179                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6180                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6181                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6182                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6183                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6184                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6185                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6186                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6187                 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
6188                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6189                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6190                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6191                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6192                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6193                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6194                 {
6195                         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
6196                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6197                         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
6198                 }
6199                 else
6200                 {
6201                         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
6202                 }
6203                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6204                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6205                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6206                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6207                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6208                 {
6209                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6210                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6211                         if (rsurface.rtlight)
6212                         {
6213                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6214                                 if (r_shadow_usingshadowmapcube)
6215                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6216                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6217                         }
6218                 }
6219
6220                 CHECKGLERROR
6221 #endif
6222                 break;
6223         case RENDERPATH_GL13:
6224         case RENDERPATH_GL11:
6225                 break;
6226         }
6227 }
6228
6229 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6230 {
6231         // select a permutation of the lighting shader appropriate to this
6232         // combination of texture, entity, light source, and fogging, only use the
6233         // minimum features necessary to avoid wasting rendering time in the
6234         // fragment shader on features that are not being used
6235         unsigned int permutation = 0;
6236         unsigned int mode = 0;
6237         const float *lightcolorbase = rtlight->currentcolor;
6238         float ambientscale = rtlight->ambientscale;
6239         float diffusescale = rtlight->diffusescale;
6240         float specularscale = rtlight->specularscale;
6241         // this is the location of the light in view space
6242         vec3_t viewlightorigin;
6243         // this transforms from view space (camera) to light space (cubemap)
6244         matrix4x4_t viewtolight;
6245         matrix4x4_t lighttoview;
6246         float viewtolight16f[16];
6247         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6248         // light source
6249         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6250         if (rtlight->currentcubemap != r_texture_whitecube)
6251                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6252         if (diffusescale > 0)
6253                 permutation |= SHADERPERMUTATION_DIFFUSE;
6254         if (specularscale > 0)
6255         {
6256                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6257                 if (r_shadow_glossexact.integer)
6258                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6259         }
6260         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6261         {
6262                 if (r_shadow_usingshadowmaprect)
6263                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6264                 if (r_shadow_usingshadowmap2d)
6265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6266                 if (r_shadow_usingshadowmapcube)
6267                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6268                 else if(r_shadow_shadowmapvsdct)
6269                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6270
6271                 if (r_shadow_shadowmapsampler)
6272                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6273                 if (r_shadow_shadowmappcf > 1)
6274                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6275                 else if (r_shadow_shadowmappcf)
6276                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6277         }
6278         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6279         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6280         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6281         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6282         switch(vid.renderpath)
6283         {
6284         case RENDERPATH_D3D9:
6285 #ifdef SUPPORTD3D
6286                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6287                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6288                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6289                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6290                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6291                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6292                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6293                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6294                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6295                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6296                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6297
6298                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6299                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6300                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6301                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6302                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6303                 if (r_shadow_usingshadowmapcube)
6304                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6305                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6306                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6307 #endif
6308                 break;
6309         case RENDERPATH_D3D10:
6310                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6311                 break;
6312         case RENDERPATH_D3D11:
6313                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6314                 break;
6315         case RENDERPATH_GL20:
6316                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6317                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6318                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6319                 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);
6320                 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);
6321                 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);
6322                 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]);
6323                 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]);
6324                 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));
6325                 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]);
6326                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6327
6328                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6329                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6330                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6331                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6332                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6333                 if (r_shadow_usingshadowmapcube)
6334                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6335                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6336                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6337                 break;
6338         case RENDERPATH_CGGL:
6339 #ifdef SUPPORTCG
6340                 R_SetupShader_SetPermutationCG(mode, permutation);
6341                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6342                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6343                 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
6344                 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
6345                 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
6346                 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
6347                 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
6348                 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
6349                 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
6350                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6351
6352                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6353                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6354                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6355                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6356                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6357                 if (r_shadow_usingshadowmapcube)
6358                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6359                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6360                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6361 #endif
6362                 break;
6363         case RENDERPATH_GL13:
6364         case RENDERPATH_GL11:
6365                 break;
6366         }
6367 }
6368
6369 #define SKINFRAME_HASH 1024
6370
6371 typedef struct
6372 {
6373         int loadsequence; // incremented each level change
6374         memexpandablearray_t array;
6375         skinframe_t *hash[SKINFRAME_HASH];
6376 }
6377 r_skinframe_t;
6378 r_skinframe_t r_skinframe;
6379
6380 void R_SkinFrame_PrepareForPurge(void)
6381 {
6382         r_skinframe.loadsequence++;
6383         // wrap it without hitting zero
6384         if (r_skinframe.loadsequence >= 200)
6385                 r_skinframe.loadsequence = 1;
6386 }
6387
6388 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6389 {
6390         if (!skinframe)
6391                 return;
6392         // mark the skinframe as used for the purging code
6393         skinframe->loadsequence = r_skinframe.loadsequence;
6394 }
6395
6396 void R_SkinFrame_Purge(void)
6397 {
6398         int i;
6399         skinframe_t *s;
6400         for (i = 0;i < SKINFRAME_HASH;i++)
6401         {
6402                 for (s = r_skinframe.hash[i];s;s = s->next)
6403                 {
6404                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6405                         {
6406                                 if (s->merged == s->base)
6407                                         s->merged = NULL;
6408                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6409                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6410                                 R_PurgeTexture(s->merged);s->merged = NULL;
6411                                 R_PurgeTexture(s->base  );s->base   = NULL;
6412                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6413                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6414                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6415                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6416                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6417                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6418                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6419                                 s->loadsequence = 0;
6420                         }
6421                 }
6422         }
6423 }
6424
6425 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6426         skinframe_t *item;
6427         char basename[MAX_QPATH];
6428
6429         Image_StripImageExtension(name, basename, sizeof(basename));
6430
6431         if( last == NULL ) {
6432                 int hashindex;
6433                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6434                 item = r_skinframe.hash[hashindex];
6435         } else {
6436                 item = last->next;
6437         }
6438
6439         // linearly search through the hash bucket
6440         for( ; item ; item = item->next ) {
6441                 if( !strcmp( item->basename, basename ) ) {
6442                         return item;
6443                 }
6444         }
6445         return NULL;
6446 }
6447
6448 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6449 {
6450         skinframe_t *item;
6451         int hashindex;
6452         char basename[MAX_QPATH];
6453
6454         Image_StripImageExtension(name, basename, sizeof(basename));
6455
6456         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6457         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6458                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6459                         break;
6460
6461         if (!item) {
6462                 rtexture_t *dyntexture;
6463                 // check whether its a dynamic texture
6464                 dyntexture = CL_GetDynTexture( basename );
6465                 if (!add && !dyntexture)
6466                         return NULL;
6467                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6468                 memset(item, 0, sizeof(*item));
6469                 strlcpy(item->basename, basename, sizeof(item->basename));
6470                 item->base = dyntexture; // either NULL or dyntexture handle
6471                 item->textureflags = textureflags;
6472                 item->comparewidth = comparewidth;
6473                 item->compareheight = compareheight;
6474                 item->comparecrc = comparecrc;
6475                 item->next = r_skinframe.hash[hashindex];
6476                 r_skinframe.hash[hashindex] = item;
6477         }
6478         else if( item->base == NULL )
6479         {
6480                 rtexture_t *dyntexture;
6481                 // check whether its a dynamic texture
6482                 // 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]
6483                 dyntexture = CL_GetDynTexture( basename );
6484                 item->base = dyntexture; // either NULL or dyntexture handle
6485         }
6486
6487         R_SkinFrame_MarkUsed(item);
6488         return item;
6489 }
6490
6491 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6492         { \
6493                 unsigned long long avgcolor[5], wsum; \
6494                 int pix, comp, w; \
6495                 avgcolor[0] = 0; \
6496                 avgcolor[1] = 0; \
6497                 avgcolor[2] = 0; \
6498                 avgcolor[3] = 0; \
6499                 avgcolor[4] = 0; \
6500                 wsum = 0; \
6501                 for(pix = 0; pix < cnt; ++pix) \
6502                 { \
6503                         w = 0; \
6504                         for(comp = 0; comp < 3; ++comp) \
6505                                 w += getpixel; \
6506                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6507                         { \
6508                                 ++wsum; \
6509                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6510                                 w = getpixel; \
6511                                 for(comp = 0; comp < 3; ++comp) \
6512                                         avgcolor[comp] += getpixel * w; \
6513                                 avgcolor[3] += w; \
6514                         } \
6515                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6516                         avgcolor[4] += getpixel; \
6517                 } \
6518                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6519                         avgcolor[3] = 1; \
6520                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6521                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6522                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6523                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6524         }
6525
6526 extern cvar_t gl_picmip;
6527 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6528 {
6529         int j;
6530         unsigned char *pixels;
6531         unsigned char *bumppixels;
6532         unsigned char *basepixels = NULL;
6533         int basepixels_width = 0;
6534         int basepixels_height = 0;
6535         skinframe_t *skinframe;
6536         rtexture_t *ddsbase = NULL;
6537         qboolean ddshasalpha = false;
6538         float ddsavgcolor[4];
6539         char basename[MAX_QPATH];
6540         int miplevel = R_PicmipForFlags(textureflags);
6541         int savemiplevel = miplevel;
6542         int mymiplevel;
6543
6544         if (cls.state == ca_dedicated)
6545                 return NULL;
6546
6547         // return an existing skinframe if already loaded
6548         // if loading of the first image fails, don't make a new skinframe as it
6549         // would cause all future lookups of this to be missing
6550         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6551         if (skinframe && skinframe->base)
6552                 return skinframe;
6553
6554         Image_StripImageExtension(name, basename, sizeof(basename));
6555
6556         // check for DDS texture file first
6557         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6558         {
6559                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6560                 if (basepixels == NULL)
6561                         return NULL;
6562         }
6563
6564         // FIXME handle miplevel
6565
6566         if (developer_loading.integer)
6567                 Con_Printf("loading skin \"%s\"\n", name);
6568
6569         // we've got some pixels to store, so really allocate this new texture now
6570         if (!skinframe)
6571                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6572         skinframe->stain = NULL;
6573         skinframe->merged = NULL;
6574         skinframe->base = NULL;
6575         skinframe->pants = NULL;
6576         skinframe->shirt = NULL;
6577         skinframe->nmap = NULL;
6578         skinframe->gloss = NULL;
6579         skinframe->glow = NULL;
6580         skinframe->fog = NULL;
6581         skinframe->reflect = NULL;
6582         skinframe->hasalpha = false;
6583
6584         if (ddsbase)
6585         {
6586                 skinframe->base = ddsbase;
6587                 skinframe->hasalpha = ddshasalpha;
6588                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6589                 if (r_loadfog && skinframe->hasalpha)
6590                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6591                 //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]);
6592         }
6593         else
6594         {
6595                 basepixels_width = image_width;
6596                 basepixels_height = image_height;
6597                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6598                 if (textureflags & TEXF_ALPHA)
6599                 {
6600                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6601                         {
6602                                 if (basepixels[j] < 255)
6603                                 {
6604                                         skinframe->hasalpha = true;
6605                                         break;
6606                                 }
6607                         }
6608                         if (r_loadfog && skinframe->hasalpha)
6609                         {
6610                                 // has transparent pixels
6611                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6612                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6613                                 {
6614                                         pixels[j+0] = 255;
6615                                         pixels[j+1] = 255;
6616                                         pixels[j+2] = 255;
6617                                         pixels[j+3] = basepixels[j+3];
6618                                 }
6619                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6620                                 Mem_Free(pixels);
6621                         }
6622                 }
6623                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6624                 //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]);
6625                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6626                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6627                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6628                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6629         }
6630
6631         if (r_loaddds)
6632         {
6633                 mymiplevel = savemiplevel;
6634                 if (r_loadnormalmap)
6635                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6636                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6637                 if (r_loadgloss)
6638                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6639                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6640                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6641                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6642         }
6643
6644         // _norm is the name used by tenebrae and has been adopted as standard
6645         if (r_loadnormalmap && skinframe->nmap == NULL)
6646         {
6647                 mymiplevel = savemiplevel;
6648                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6649                 {
6650                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6651                         Mem_Free(pixels);
6652                         pixels = NULL;
6653                 }
6654                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6655                 {
6656                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6657                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6658                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6659                         Mem_Free(pixels);
6660                         Mem_Free(bumppixels);
6661                 }
6662                 else if (r_shadow_bumpscale_basetexture.value > 0)
6663                 {
6664                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6665                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6666                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6667                         Mem_Free(pixels);
6668                 }
6669                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6670                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6671         }
6672
6673         // _luma is supported only for tenebrae compatibility
6674         // _glow is the preferred name
6675         mymiplevel = savemiplevel;
6676         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))))
6677         {
6678                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6679                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6680                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6681                 Mem_Free(pixels);pixels = NULL;
6682         }
6683
6684         mymiplevel = savemiplevel;
6685         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6686         {
6687                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6688                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6689                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6690                 Mem_Free(pixels);
6691                 pixels = NULL;
6692         }
6693
6694         mymiplevel = savemiplevel;
6695         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6696         {
6697                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6698                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6699                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6700                 Mem_Free(pixels);
6701                 pixels = NULL;
6702         }
6703
6704         mymiplevel = savemiplevel;
6705         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6706         {
6707                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6708                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6709                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6710                 Mem_Free(pixels);
6711                 pixels = NULL;
6712         }
6713
6714         mymiplevel = savemiplevel;
6715         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6716         {
6717                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6718                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6719                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6720                 Mem_Free(pixels);
6721                 pixels = NULL;
6722         }
6723
6724         if (basepixels)
6725                 Mem_Free(basepixels);
6726
6727         return skinframe;
6728 }
6729
6730 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6731 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6732 {
6733         int i;
6734         unsigned char *temp1, *temp2;
6735         skinframe_t *skinframe;
6736
6737         if (cls.state == ca_dedicated)
6738                 return NULL;
6739
6740         // if already loaded just return it, otherwise make a new skinframe
6741         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6742         if (skinframe && skinframe->base)
6743                 return skinframe;
6744
6745         skinframe->stain = NULL;
6746         skinframe->merged = NULL;
6747         skinframe->base = NULL;
6748         skinframe->pants = NULL;
6749         skinframe->shirt = NULL;
6750         skinframe->nmap = NULL;
6751         skinframe->gloss = NULL;
6752         skinframe->glow = NULL;
6753         skinframe->fog = NULL;
6754         skinframe->reflect = NULL;
6755         skinframe->hasalpha = false;
6756
6757         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6758         if (!skindata)
6759                 return NULL;
6760
6761         if (developer_loading.integer)
6762                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6763
6764         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6765         {
6766                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6767                 temp2 = temp1 + width * height * 4;
6768                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6769                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6770                 Mem_Free(temp1);
6771         }
6772         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6773         if (textureflags & TEXF_ALPHA)
6774         {
6775                 for (i = 3;i < width * height * 4;i += 4)
6776                 {
6777                         if (skindata[i] < 255)
6778                         {
6779                                 skinframe->hasalpha = true;
6780                                 break;
6781                         }
6782                 }
6783                 if (r_loadfog && skinframe->hasalpha)
6784                 {
6785                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6786                         memcpy(fogpixels, skindata, width * height * 4);
6787                         for (i = 0;i < width * height * 4;i += 4)
6788                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6789                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6790                         Mem_Free(fogpixels);
6791                 }
6792         }
6793
6794         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6795         //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]);
6796
6797         return skinframe;
6798 }
6799
6800 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6801 {
6802         int i;
6803         int featuresmask;
6804         skinframe_t *skinframe;
6805
6806         if (cls.state == ca_dedicated)
6807                 return NULL;
6808
6809         // if already loaded just return it, otherwise make a new skinframe
6810         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6811         if (skinframe && skinframe->base)
6812                 return skinframe;
6813
6814         skinframe->stain = NULL;
6815         skinframe->merged = NULL;
6816         skinframe->base = NULL;
6817         skinframe->pants = NULL;
6818         skinframe->shirt = NULL;
6819         skinframe->nmap = NULL;
6820         skinframe->gloss = NULL;
6821         skinframe->glow = NULL;
6822         skinframe->fog = NULL;
6823         skinframe->reflect = NULL;
6824         skinframe->hasalpha = false;
6825
6826         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6827         if (!skindata)
6828                 return NULL;
6829
6830         if (developer_loading.integer)
6831                 Con_Printf("loading quake skin \"%s\"\n", name);
6832
6833         // 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)
6834         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6835         memcpy(skinframe->qpixels, skindata, width*height);
6836         skinframe->qwidth = width;
6837         skinframe->qheight = height;
6838
6839         featuresmask = 0;
6840         for (i = 0;i < width * height;i++)
6841                 featuresmask |= palette_featureflags[skindata[i]];
6842
6843         skinframe->hasalpha = false;
6844         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6845         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6846         skinframe->qgeneratemerged = true;
6847         skinframe->qgeneratebase = skinframe->qhascolormapping;
6848         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6849
6850         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6851         //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]);
6852
6853         return skinframe;
6854 }
6855
6856 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6857 {
6858         int width;
6859         int height;
6860         unsigned char *skindata;
6861
6862         if (!skinframe->qpixels)
6863                 return;
6864
6865         if (!skinframe->qhascolormapping)
6866                 colormapped = false;
6867
6868         if (colormapped)
6869         {
6870                 if (!skinframe->qgeneratebase)
6871                         return;
6872         }
6873         else
6874         {
6875                 if (!skinframe->qgeneratemerged)
6876                         return;
6877         }
6878
6879         width = skinframe->qwidth;
6880         height = skinframe->qheight;
6881         skindata = skinframe->qpixels;
6882
6883         if (skinframe->qgeneratenmap)
6884         {
6885                 unsigned char *temp1, *temp2;
6886                 skinframe->qgeneratenmap = false;
6887                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6888                 temp2 = temp1 + width * height * 4;
6889                 // use either a custom palette or the quake palette
6890                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6891                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6892                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6893                 Mem_Free(temp1);
6894         }
6895
6896         if (skinframe->qgenerateglow)
6897         {
6898                 skinframe->qgenerateglow = false;
6899                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6900         }
6901
6902         if (colormapped)
6903         {
6904                 skinframe->qgeneratebase = false;
6905                 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);
6906                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6907                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6908         }
6909         else
6910         {
6911                 skinframe->qgeneratemerged = false;
6912                 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);
6913         }
6914
6915         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6916         {
6917                 Mem_Free(skinframe->qpixels);
6918                 skinframe->qpixels = NULL;
6919         }
6920 }
6921
6922 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)
6923 {
6924         int i;
6925         skinframe_t *skinframe;
6926
6927         if (cls.state == ca_dedicated)
6928                 return NULL;
6929
6930         // if already loaded just return it, otherwise make a new skinframe
6931         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6932         if (skinframe && skinframe->base)
6933                 return skinframe;
6934
6935         skinframe->stain = NULL;
6936         skinframe->merged = NULL;
6937         skinframe->base = NULL;
6938         skinframe->pants = NULL;
6939         skinframe->shirt = NULL;
6940         skinframe->nmap = NULL;
6941         skinframe->gloss = NULL;
6942         skinframe->glow = NULL;
6943         skinframe->fog = NULL;
6944         skinframe->reflect = NULL;
6945         skinframe->hasalpha = false;
6946
6947         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6948         if (!skindata)
6949                 return NULL;
6950
6951         if (developer_loading.integer)
6952                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6953
6954         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6955         if (textureflags & TEXF_ALPHA)
6956         {
6957                 for (i = 0;i < width * height;i++)
6958                 {
6959                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6960                         {
6961                                 skinframe->hasalpha = true;
6962                                 break;
6963                         }
6964                 }
6965                 if (r_loadfog && skinframe->hasalpha)
6966                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6967         }
6968
6969         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6970         //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]);
6971
6972         return skinframe;
6973 }
6974
6975 skinframe_t *R_SkinFrame_LoadMissing(void)
6976 {
6977         skinframe_t *skinframe;
6978
6979         if (cls.state == ca_dedicated)
6980                 return NULL;
6981
6982         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6983         skinframe->stain = NULL;
6984         skinframe->merged = NULL;
6985         skinframe->base = NULL;
6986         skinframe->pants = NULL;
6987         skinframe->shirt = NULL;
6988         skinframe->nmap = NULL;
6989         skinframe->gloss = NULL;
6990         skinframe->glow = NULL;
6991         skinframe->fog = NULL;
6992         skinframe->reflect = NULL;
6993         skinframe->hasalpha = false;
6994
6995         skinframe->avgcolor[0] = rand() / RAND_MAX;
6996         skinframe->avgcolor[1] = rand() / RAND_MAX;
6997         skinframe->avgcolor[2] = rand() / RAND_MAX;
6998         skinframe->avgcolor[3] = 1;
6999
7000         return skinframe;
7001 }
7002
7003 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7004 typedef struct suffixinfo_s
7005 {
7006         const char *suffix;
7007         qboolean flipx, flipy, flipdiagonal;
7008 }
7009 suffixinfo_t;
7010 static suffixinfo_t suffix[3][6] =
7011 {
7012         {
7013                 {"px",   false, false, false},
7014                 {"nx",   false, false, false},
7015                 {"py",   false, false, false},
7016                 {"ny",   false, false, false},
7017                 {"pz",   false, false, false},
7018                 {"nz",   false, false, false}
7019         },
7020         {
7021                 {"posx", false, false, false},
7022                 {"negx", false, false, false},
7023                 {"posy", false, false, false},
7024                 {"negy", false, false, false},
7025                 {"posz", false, false, false},
7026                 {"negz", false, false, false}
7027         },
7028         {
7029                 {"rt",    true, false,  true},
7030                 {"lf",   false,  true,  true},
7031                 {"ft",    true,  true, false},
7032                 {"bk",   false, false, false},
7033                 {"up",    true, false,  true},
7034                 {"dn",    true, false,  true}
7035         }
7036 };
7037
7038 static int componentorder[4] = {0, 1, 2, 3};
7039
7040 rtexture_t *R_LoadCubemap(const char *basename)
7041 {
7042         int i, j, cubemapsize;
7043         unsigned char *cubemappixels, *image_buffer;
7044         rtexture_t *cubemaptexture;
7045         char name[256];
7046         // must start 0 so the first loadimagepixels has no requested width/height
7047         cubemapsize = 0;
7048         cubemappixels = NULL;
7049         cubemaptexture = NULL;
7050         // keep trying different suffix groups (posx, px, rt) until one loads
7051         for (j = 0;j < 3 && !cubemappixels;j++)
7052         {
7053                 // load the 6 images in the suffix group
7054                 for (i = 0;i < 6;i++)
7055                 {
7056                         // generate an image name based on the base and and suffix
7057                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7058                         // load it
7059                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7060                         {
7061                                 // an image loaded, make sure width and height are equal
7062                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7063                                 {
7064                                         // if this is the first image to load successfully, allocate the cubemap memory
7065                                         if (!cubemappixels && image_width >= 1)
7066                                         {
7067                                                 cubemapsize = image_width;
7068                                                 // note this clears to black, so unavailable sides are black
7069                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7070                                         }
7071                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7072                                         if (cubemappixels)
7073                                                 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);
7074                                 }
7075                                 else
7076                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7077                                 // free the image
7078                                 Mem_Free(image_buffer);
7079                         }
7080                 }
7081         }
7082         // if a cubemap loaded, upload it
7083         if (cubemappixels)
7084         {
7085                 if (developer_loading.integer)
7086                         Con_Printf("loading cubemap \"%s\"\n", basename);
7087
7088                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7089                 Mem_Free(cubemappixels);
7090         }
7091         else
7092         {
7093                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7094                 if (developer_loading.integer)
7095                 {
7096                         Con_Printf("(tried tried images ");
7097                         for (j = 0;j < 3;j++)
7098                                 for (i = 0;i < 6;i++)
7099                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7100                         Con_Print(" and was unable to find any of them).\n");
7101                 }
7102         }
7103         return cubemaptexture;
7104 }
7105
7106 rtexture_t *R_GetCubemap(const char *basename)
7107 {
7108         int i;
7109         for (i = 0;i < r_texture_numcubemaps;i++)
7110                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7111                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7112         if (i >= MAX_CUBEMAPS)
7113                 return r_texture_whitecube;
7114         r_texture_numcubemaps++;
7115         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7116         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7117         return r_texture_cubemaps[i].texture;
7118 }
7119
7120 void R_FreeCubemaps(void)
7121 {
7122         int i;
7123         for (i = 0;i < r_texture_numcubemaps;i++)
7124         {
7125                 if (developer_loading.integer)
7126                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7127                 if (r_texture_cubemaps[i].texture)
7128                         R_FreeTexture(r_texture_cubemaps[i].texture);
7129         }
7130         r_texture_numcubemaps = 0;
7131 }
7132
7133 void R_Main_FreeViewCache(void)
7134 {
7135         if (r_refdef.viewcache.entityvisible)
7136                 Mem_Free(r_refdef.viewcache.entityvisible);
7137         if (r_refdef.viewcache.world_pvsbits)
7138                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7139         if (r_refdef.viewcache.world_leafvisible)
7140                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7141         if (r_refdef.viewcache.world_surfacevisible)
7142                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7143         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7144 }
7145
7146 void R_Main_ResizeViewCache(void)
7147 {
7148         int numentities = r_refdef.scene.numentities;
7149         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7150         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7151         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7152         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7153         if (r_refdef.viewcache.maxentities < numentities)
7154         {
7155                 r_refdef.viewcache.maxentities = numentities;
7156                 if (r_refdef.viewcache.entityvisible)
7157                         Mem_Free(r_refdef.viewcache.entityvisible);
7158                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7159         }
7160         if (r_refdef.viewcache.world_numclusters != numclusters)
7161         {
7162                 r_refdef.viewcache.world_numclusters = numclusters;
7163                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7164                 if (r_refdef.viewcache.world_pvsbits)
7165                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7166                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7167         }
7168         if (r_refdef.viewcache.world_numleafs != numleafs)
7169         {
7170                 r_refdef.viewcache.world_numleafs = numleafs;
7171                 if (r_refdef.viewcache.world_leafvisible)
7172                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7173                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7174         }
7175         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7176         {
7177                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7178                 if (r_refdef.viewcache.world_surfacevisible)
7179                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7180                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7181         }
7182 }
7183
7184 extern rtexture_t *loadingscreentexture;
7185 void gl_main_start(void)
7186 {
7187         loadingscreentexture = NULL;
7188         r_texture_blanknormalmap = NULL;
7189         r_texture_white = NULL;
7190         r_texture_grey128 = NULL;
7191         r_texture_black = NULL;
7192         r_texture_whitecube = NULL;
7193         r_texture_normalizationcube = NULL;
7194         r_texture_fogattenuation = NULL;
7195         r_texture_fogheighttexture = NULL;
7196         r_texture_gammaramps = NULL;
7197         r_texture_numcubemaps = 0;
7198
7199         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7200         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7201
7202         switch(vid.renderpath)
7203         {
7204         case RENDERPATH_GL20:
7205         case RENDERPATH_CGGL:
7206         case RENDERPATH_D3D9:
7207         case RENDERPATH_D3D10:
7208         case RENDERPATH_D3D11:
7209                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7210                 Cvar_SetValueQuick(&gl_combine, 1);
7211                 Cvar_SetValueQuick(&r_glsl, 1);
7212                 r_loadnormalmap = true;
7213                 r_loadgloss = true;
7214                 r_loadfog = false;
7215                 break;
7216         case RENDERPATH_GL13:
7217                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7218                 Cvar_SetValueQuick(&gl_combine, 1);
7219                 Cvar_SetValueQuick(&r_glsl, 0);
7220                 r_loadnormalmap = false;
7221                 r_loadgloss = false;
7222                 r_loadfog = true;
7223                 break;
7224         case RENDERPATH_GL11:
7225                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7226                 Cvar_SetValueQuick(&gl_combine, 0);
7227                 Cvar_SetValueQuick(&r_glsl, 0);
7228                 r_loadnormalmap = false;
7229                 r_loadgloss = false;
7230                 r_loadfog = true;
7231                 break;
7232         }
7233
7234         R_AnimCache_Free();
7235         R_FrameData_Reset();
7236
7237         r_numqueries = 0;
7238         r_maxqueries = 0;
7239         memset(r_queries, 0, sizeof(r_queries));
7240
7241         r_qwskincache = NULL;
7242         r_qwskincache_size = 0;
7243
7244         // set up r_skinframe loading system for textures
7245         memset(&r_skinframe, 0, sizeof(r_skinframe));
7246         r_skinframe.loadsequence = 1;
7247         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7248
7249         r_main_texturepool = R_AllocTexturePool();
7250         R_BuildBlankTextures();
7251         R_BuildNoTexture();
7252         if (vid.support.arb_texture_cube_map)
7253         {
7254                 R_BuildWhiteCube();
7255                 R_BuildNormalizationCube();
7256         }
7257         r_texture_fogattenuation = NULL;
7258         r_texture_fogheighttexture = NULL;
7259         r_texture_gammaramps = NULL;
7260         //r_texture_fogintensity = NULL;
7261         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7262         memset(&r_waterstate, 0, sizeof(r_waterstate));
7263         r_glsl_permutation = NULL;
7264         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7265         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7266         glslshaderstring = NULL;
7267 #ifdef SUPPORTCG
7268         r_cg_permutation = NULL;
7269         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7270         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7271         cgshaderstring = NULL;
7272 #endif
7273 #ifdef SUPPORTD3D
7274         r_hlsl_permutation = NULL;
7275         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7276         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7277         hlslshaderstring = NULL;
7278 #endif
7279         memset(&r_svbsp, 0, sizeof (r_svbsp));
7280
7281         r_refdef.fogmasktable_density = 0;
7282 }
7283
7284 void gl_main_shutdown(void)
7285 {
7286         R_AnimCache_Free();
7287         R_FrameData_Reset();
7288
7289         R_Main_FreeViewCache();
7290
7291         switch(vid.renderpath)
7292         {
7293         case RENDERPATH_GL11:
7294         case RENDERPATH_GL13:
7295         case RENDERPATH_GL20:
7296         case RENDERPATH_CGGL:
7297                 if (r_maxqueries)
7298                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7299                 break;
7300         case RENDERPATH_D3D9:
7301                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7302                 break;
7303         case RENDERPATH_D3D10:
7304                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7305                 break;
7306         case RENDERPATH_D3D11:
7307                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7308                 break;
7309         }
7310
7311         r_numqueries = 0;
7312         r_maxqueries = 0;
7313         memset(r_queries, 0, sizeof(r_queries));
7314
7315         r_qwskincache = NULL;
7316         r_qwskincache_size = 0;
7317
7318         // clear out the r_skinframe state
7319         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7320         memset(&r_skinframe, 0, sizeof(r_skinframe));
7321
7322         if (r_svbsp.nodes)
7323                 Mem_Free(r_svbsp.nodes);
7324         memset(&r_svbsp, 0, sizeof (r_svbsp));
7325         R_FreeTexturePool(&r_main_texturepool);
7326         loadingscreentexture = NULL;
7327         r_texture_blanknormalmap = NULL;
7328         r_texture_white = NULL;
7329         r_texture_grey128 = NULL;
7330         r_texture_black = NULL;
7331         r_texture_whitecube = NULL;
7332         r_texture_normalizationcube = NULL;
7333         r_texture_fogattenuation = NULL;
7334         r_texture_fogheighttexture = NULL;
7335         r_texture_gammaramps = NULL;
7336         r_texture_numcubemaps = 0;
7337         //r_texture_fogintensity = NULL;
7338         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7339         memset(&r_waterstate, 0, sizeof(r_waterstate));
7340         R_GLSL_Restart_f();
7341 }
7342
7343 extern void CL_ParseEntityLump(char *entitystring);
7344 void gl_main_newmap(void)
7345 {
7346         // FIXME: move this code to client
7347         char *entities, entname[MAX_QPATH];
7348         if (r_qwskincache)
7349                 Mem_Free(r_qwskincache);
7350         r_qwskincache = NULL;
7351         r_qwskincache_size = 0;
7352         if (cl.worldmodel)
7353         {
7354                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7355                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7356                 {
7357                         CL_ParseEntityLump(entities);
7358                         Mem_Free(entities);
7359                         return;
7360                 }
7361                 if (cl.worldmodel->brush.entities)
7362                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7363         }
7364         R_Main_FreeViewCache();
7365
7366         R_FrameData_Reset();
7367 }
7368
7369 void GL_Main_Init(void)
7370 {
7371         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7372
7373         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7374         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7375         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7376         if (gamemode == GAME_NEHAHRA)
7377         {
7378                 Cvar_RegisterVariable (&gl_fogenable);
7379                 Cvar_RegisterVariable (&gl_fogdensity);
7380                 Cvar_RegisterVariable (&gl_fogred);
7381                 Cvar_RegisterVariable (&gl_foggreen);
7382                 Cvar_RegisterVariable (&gl_fogblue);
7383                 Cvar_RegisterVariable (&gl_fogstart);
7384                 Cvar_RegisterVariable (&gl_fogend);
7385                 Cvar_RegisterVariable (&gl_skyclip);
7386         }
7387         Cvar_RegisterVariable(&r_motionblur);
7388         Cvar_RegisterVariable(&r_motionblur_maxblur);
7389         Cvar_RegisterVariable(&r_motionblur_bmin);
7390         Cvar_RegisterVariable(&r_motionblur_vmin);
7391         Cvar_RegisterVariable(&r_motionblur_vmax);
7392         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7393         Cvar_RegisterVariable(&r_motionblur_randomize);
7394         Cvar_RegisterVariable(&r_damageblur);
7395         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7396         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7397         Cvar_RegisterVariable(&r_equalize_entities_by);
7398         Cvar_RegisterVariable(&r_equalize_entities_to);
7399         Cvar_RegisterVariable(&r_depthfirst);
7400         Cvar_RegisterVariable(&r_useinfinitefarclip);
7401         Cvar_RegisterVariable(&r_farclip_base);
7402         Cvar_RegisterVariable(&r_farclip_world);
7403         Cvar_RegisterVariable(&r_nearclip);
7404         Cvar_RegisterVariable(&r_showbboxes);
7405         Cvar_RegisterVariable(&r_showsurfaces);
7406         Cvar_RegisterVariable(&r_showtris);
7407         Cvar_RegisterVariable(&r_shownormals);
7408         Cvar_RegisterVariable(&r_showlighting);
7409         Cvar_RegisterVariable(&r_showshadowvolumes);
7410         Cvar_RegisterVariable(&r_showcollisionbrushes);
7411         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7412         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7413         Cvar_RegisterVariable(&r_showdisabledepthtest);
7414         Cvar_RegisterVariable(&r_drawportals);
7415         Cvar_RegisterVariable(&r_drawentities);
7416         Cvar_RegisterVariable(&r_draw2d);
7417         Cvar_RegisterVariable(&r_drawworld);
7418         Cvar_RegisterVariable(&r_cullentities_trace);
7419         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7420         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7421         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7422         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7423         Cvar_RegisterVariable(&r_drawviewmodel);
7424         Cvar_RegisterVariable(&r_drawexteriormodel);
7425         Cvar_RegisterVariable(&r_speeds);
7426         Cvar_RegisterVariable(&r_fullbrights);
7427         Cvar_RegisterVariable(&r_wateralpha);
7428         Cvar_RegisterVariable(&r_dynamic);
7429         Cvar_RegisterVariable(&r_fullbright);
7430         Cvar_RegisterVariable(&r_shadows);
7431         Cvar_RegisterVariable(&r_shadows_darken);
7432         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7433         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7434         Cvar_RegisterVariable(&r_shadows_throwdistance);
7435         Cvar_RegisterVariable(&r_shadows_throwdirection);
7436         Cvar_RegisterVariable(&r_shadows_focus);
7437         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7438         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7439         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7440         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7441         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7442         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7443         Cvar_RegisterVariable(&r_fog_exp2);
7444         Cvar_RegisterVariable(&r_drawfog);
7445         Cvar_RegisterVariable(&r_transparentdepthmasking);
7446         Cvar_RegisterVariable(&r_texture_dds_load);
7447         Cvar_RegisterVariable(&r_texture_dds_save);
7448         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7449         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7450         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7451         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7452         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7453         Cvar_RegisterVariable(&r_textureunits);
7454         Cvar_RegisterVariable(&gl_combine);
7455         Cvar_RegisterVariable(&r_glsl);
7456         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7457         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7458         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7459         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7460         Cvar_RegisterVariable(&r_glsl_postprocess);
7461         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7462         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7463         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7464         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7465         Cvar_RegisterVariable(&r_water);
7466         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7467         Cvar_RegisterVariable(&r_water_clippingplanebias);
7468         Cvar_RegisterVariable(&r_water_refractdistort);
7469         Cvar_RegisterVariable(&r_water_reflectdistort);
7470         Cvar_RegisterVariable(&r_lerpsprites);
7471         Cvar_RegisterVariable(&r_lerpmodels);
7472         Cvar_RegisterVariable(&r_lerplightstyles);
7473         Cvar_RegisterVariable(&r_waterscroll);
7474         Cvar_RegisterVariable(&r_bloom);
7475         Cvar_RegisterVariable(&r_bloom_colorscale);
7476         Cvar_RegisterVariable(&r_bloom_brighten);
7477         Cvar_RegisterVariable(&r_bloom_blur);
7478         Cvar_RegisterVariable(&r_bloom_resolution);
7479         Cvar_RegisterVariable(&r_bloom_colorexponent);
7480         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7481         Cvar_RegisterVariable(&r_hdr);
7482         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7483         Cvar_RegisterVariable(&r_hdr_glowintensity);
7484         Cvar_RegisterVariable(&r_hdr_range);
7485         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7486         Cvar_RegisterVariable(&developer_texturelogging);
7487         Cvar_RegisterVariable(&gl_lightmaps);
7488         Cvar_RegisterVariable(&r_test);
7489         Cvar_RegisterVariable(&r_glsl_saturation);
7490         Cvar_RegisterVariable(&r_framedatasize);
7491         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7492                 Cvar_SetValue("r_fullbrights", 0);
7493         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7494
7495         Cvar_RegisterVariable(&r_track_sprites);
7496         Cvar_RegisterVariable(&r_track_sprites_flags);
7497         Cvar_RegisterVariable(&r_track_sprites_scalew);
7498         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7499         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7500         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7501 }
7502
7503 extern void R_Textures_Init(void);
7504 extern void GL_Draw_Init(void);
7505 extern void GL_Main_Init(void);
7506 extern void R_Shadow_Init(void);
7507 extern void R_Sky_Init(void);
7508 extern void GL_Surf_Init(void);
7509 extern void R_Particles_Init(void);
7510 extern void R_Explosion_Init(void);
7511 extern void gl_backend_init(void);
7512 extern void Sbar_Init(void);
7513 extern void R_LightningBeams_Init(void);
7514 extern void Mod_RenderInit(void);
7515 extern void Font_Init(void);
7516
7517 void Render_Init(void)
7518 {
7519         gl_backend_init();
7520         R_Textures_Init();
7521         GL_Main_Init();
7522         Font_Init();
7523         GL_Draw_Init();
7524         R_Shadow_Init();
7525         R_Sky_Init();
7526         GL_Surf_Init();
7527         Sbar_Init();
7528         R_Particles_Init();
7529         R_Explosion_Init();
7530         R_LightningBeams_Init();
7531         Mod_RenderInit();
7532 }
7533
7534 /*
7535 ===============
7536 GL_Init
7537 ===============
7538 */
7539 extern char *ENGINE_EXTENSIONS;
7540 void GL_Init (void)
7541 {
7542         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7543         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7544         gl_version = (const char *)qglGetString(GL_VERSION);
7545         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7546
7547         if (!gl_extensions)
7548                 gl_extensions = "";
7549         if (!gl_platformextensions)
7550                 gl_platformextensions = "";
7551
7552         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7553         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7554         Con_Printf("GL_VERSION: %s\n", gl_version);
7555         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7556         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7557
7558         VID_CheckExtensions();
7559
7560         // LordHavoc: report supported extensions
7561         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7562
7563         // clear to black (loading plaque will be seen over this)
7564         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7565 }
7566
7567 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7568 {
7569         int i;
7570         mplane_t *p;
7571         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7572         {
7573                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7574                 if (i == 4)
7575                         continue;
7576                 p = r_refdef.view.frustum + i;
7577                 switch(p->signbits)
7578                 {
7579                 default:
7580                 case 0:
7581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7582                                 return true;
7583                         break;
7584                 case 1:
7585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7586                                 return true;
7587                         break;
7588                 case 2:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 3:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 4:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 5:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 6:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 7:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 }
7613         }
7614         return false;
7615 }
7616
7617 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7618 {
7619         int i;
7620         const mplane_t *p;
7621         for (i = 0;i < numplanes;i++)
7622         {
7623                 p = planes + i;
7624                 switch(p->signbits)
7625                 {
7626                 default:
7627                 case 0:
7628                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7629                                 return true;
7630                         break;
7631                 case 1:
7632                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7633                                 return true;
7634                         break;
7635                 case 2:
7636                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7637                                 return true;
7638                         break;
7639                 case 3:
7640                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7641                                 return true;
7642                         break;
7643                 case 4:
7644                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7645                                 return true;
7646                         break;
7647                 case 5:
7648                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7649                                 return true;
7650                         break;
7651                 case 6:
7652                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7653                                 return true;
7654                         break;
7655                 case 7:
7656                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7657                                 return true;
7658                         break;
7659                 }
7660         }
7661         return false;
7662 }
7663
7664 //==================================================================================
7665
7666 // LordHavoc: this stores temporary data used within the same frame
7667
7668 qboolean r_framedata_failed;
7669 static size_t r_framedata_size;
7670 static size_t r_framedata_current;
7671 static void *r_framedata_base;
7672
7673 void R_FrameData_Reset(void)
7674 {
7675         if (r_framedata_base)
7676                 Mem_Free(r_framedata_base);
7677         r_framedata_base = NULL;
7678         r_framedata_size = 0;
7679         r_framedata_current = 0;
7680         r_framedata_failed = false;
7681 }
7682
7683 void R_FrameData_NewFrame(void)
7684 {
7685         size_t wantedsize;
7686         if (r_framedata_failed)
7687                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7688         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7689         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7690         if (r_framedata_size != wantedsize)
7691         {
7692                 r_framedata_size = wantedsize;
7693                 if (r_framedata_base)
7694                         Mem_Free(r_framedata_base);
7695                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7696         }
7697         r_framedata_current = 0;
7698         r_framedata_failed = false;
7699 }
7700
7701 void *R_FrameData_Alloc(size_t size)
7702 {
7703         void *data;
7704
7705         // align to 16 byte boundary
7706         size = (size + 15) & ~15;
7707         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7708         r_framedata_current += size;
7709
7710         // check overflow
7711         if (r_framedata_current > r_framedata_size)
7712                 r_framedata_failed = true;
7713
7714         // return NULL on everything after a failure
7715         if (r_framedata_failed)
7716                 return NULL;
7717
7718         return data;
7719 }
7720
7721 void *R_FrameData_Store(size_t size, void *data)
7722 {
7723         void *d = R_FrameData_Alloc(size);
7724         if (d)
7725                 memcpy(d, data, size);
7726         return d;
7727 }
7728
7729 //==================================================================================
7730
7731 // LordHavoc: animcache originally written by Echon, rewritten since then
7732
7733 /**
7734  * Animation cache prevents re-generating mesh data for an animated model
7735  * multiple times in one frame for lighting, shadowing, reflections, etc.
7736  */
7737
7738 void R_AnimCache_Free(void)
7739 {
7740 }
7741
7742 void R_AnimCache_ClearCache(void)
7743 {
7744         int i;
7745         entity_render_t *ent;
7746
7747         for (i = 0;i < r_refdef.scene.numentities;i++)
7748         {
7749                 ent = r_refdef.scene.entities[i];
7750                 ent->animcache_vertex3f = NULL;
7751                 ent->animcache_normal3f = NULL;
7752                 ent->animcache_svector3f = NULL;
7753                 ent->animcache_tvector3f = NULL;
7754                 ent->animcache_vertexposition = NULL;
7755                 ent->animcache_vertexmesh = NULL;
7756                 ent->animcache_vertexpositionbuffer = NULL;
7757                 ent->animcache_vertexmeshbuffer = NULL;
7758         }
7759 }
7760
7761 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7762 {
7763         int i;
7764         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7765                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7766         if (!ent->animcache_vertexposition)
7767                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7768         if (ent->animcache_vertexposition)
7769         {
7770                 for (i = 0;i < numvertices;i++)
7771                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
7772                 // TODO: upload vertex buffer?
7773         }
7774         if (ent->animcache_vertexmesh)
7775         {
7776                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7777                 for (i = 0;i < numvertices;i++)
7778                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
7779                 if (ent->animcache_svector3f)
7780                         for (i = 0;i < numvertices;i++)
7781                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
7782                 if (ent->animcache_tvector3f)
7783                         for (i = 0;i < numvertices;i++)
7784                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
7785                 if (ent->animcache_normal3f)
7786                         for (i = 0;i < numvertices;i++)
7787                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
7788                 // TODO: upload vertex buffer?
7789         }
7790 }
7791
7792 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7793 {
7794         dp_model_t *model = ent->model;
7795         int numvertices;
7796         // see if it's already cached this frame
7797         if (ent->animcache_vertex3f)
7798         {
7799                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7800                 if (wantnormals || wanttangents)
7801                 {
7802                         if (ent->animcache_normal3f)
7803                                 wantnormals = false;
7804                         if (ent->animcache_svector3f)
7805                                 wanttangents = false;
7806                         if (wantnormals || wanttangents)
7807                         {
7808                                 numvertices = model->surfmesh.num_vertices;
7809                                 if (wantnormals)
7810                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7811                                 if (wanttangents)
7812                                 {
7813                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815                                 }
7816                                 if (!r_framedata_failed)
7817                                 {
7818                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7819                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7820                                 }
7821                         }
7822                 }
7823         }
7824         else
7825         {
7826                 // see if this ent is worth caching
7827                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7828                         return false;
7829                 // get some memory for this entity and generate mesh data
7830                 numvertices = model->surfmesh.num_vertices;
7831                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7832                 if (wantnormals)
7833                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7834                 if (wanttangents)
7835                 {
7836                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7837                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7838                 }
7839                 if (!r_framedata_failed)
7840                 {
7841                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7842                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7843                 }
7844         }
7845         return !r_framedata_failed;
7846 }
7847
7848 void R_AnimCache_CacheVisibleEntities(void)
7849 {
7850         int i;
7851         qboolean wantnormals = true;
7852         qboolean wanttangents = !r_showsurfaces.integer;
7853
7854         switch(vid.renderpath)
7855         {
7856         case RENDERPATH_GL20:
7857         case RENDERPATH_CGGL:
7858         case RENDERPATH_D3D9:
7859         case RENDERPATH_D3D10:
7860         case RENDERPATH_D3D11:
7861                 break;
7862         case RENDERPATH_GL13:
7863         case RENDERPATH_GL11:
7864                 wanttangents = false;
7865                 break;
7866         }
7867
7868         if (r_shownormals.integer)
7869                 wanttangents = wantnormals = true;
7870
7871         // TODO: thread this
7872         // NOTE: R_PrepareRTLights() also caches entities
7873
7874         for (i = 0;i < r_refdef.scene.numentities;i++)
7875                 if (r_refdef.viewcache.entityvisible[i])
7876                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7877 }
7878
7879 //==================================================================================
7880
7881 static void R_View_UpdateEntityLighting (void)
7882 {
7883         int i;
7884         entity_render_t *ent;
7885         vec3_t tempdiffusenormal, avg;
7886         vec_t f, fa, fd, fdd;
7887         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7888
7889         for (i = 0;i < r_refdef.scene.numentities;i++)
7890         {
7891                 ent = r_refdef.scene.entities[i];
7892
7893                 // skip unseen models
7894                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7895                         continue;
7896
7897                 // skip bsp models
7898                 if (ent->model && ent->model->brush.num_leafs)
7899                 {
7900                         // TODO: use modellight for r_ambient settings on world?
7901                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7902                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7903                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7904                         continue;
7905                 }
7906
7907                 // fetch the lighting from the worldmodel data
7908                 VectorClear(ent->modellight_ambient);
7909                 VectorClear(ent->modellight_diffuse);
7910                 VectorClear(tempdiffusenormal);
7911                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7912                 {
7913                         vec3_t org;
7914                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7915                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7916                         if(ent->flags & RENDER_EQUALIZE)
7917                         {
7918                                 // first fix up ambient lighting...
7919                                 if(r_equalize_entities_minambient.value > 0)
7920                                 {
7921                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7922                                         if(fd > 0)
7923                                         {
7924                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7925                                                 if(fa < r_equalize_entities_minambient.value * fd)
7926                                                 {
7927                                                         // solve:
7928                                                         //   fa'/fd' = minambient
7929                                                         //   fa'+0.25*fd' = fa+0.25*fd
7930                                                         //   ...
7931                                                         //   fa' = fd' * minambient
7932                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7933                                                         //   ...
7934                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7935                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7936                                                         //   ...
7937                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7938                                                         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
7939                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7940                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7941                                                 }
7942                                         }
7943                                 }
7944
7945                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7946                                 {
7947                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7948                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7949                                         if(f > 0)
7950                                         {
7951                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7952                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7953                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7954                                         }
7955                                 }
7956                         }
7957                 }
7958                 else // highly rare
7959                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7960
7961                 // move the light direction into modelspace coordinates for lighting code
7962                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7963                 if(VectorLength2(ent->modellight_lightdir) == 0)
7964                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7965                 VectorNormalize(ent->modellight_lightdir);
7966         }
7967 }
7968
7969 #define MAX_LINEOFSIGHTTRACES 64
7970
7971 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7972 {
7973         int i;
7974         vec3_t boxmins, boxmaxs;
7975         vec3_t start;
7976         vec3_t end;
7977         dp_model_t *model = r_refdef.scene.worldmodel;
7978
7979         if (!model || !model->brush.TraceLineOfSight)
7980                 return true;
7981
7982         // expand the box a little
7983         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7984         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7985         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7986         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7987         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7988         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7989
7990         // return true if eye is inside enlarged box
7991         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7992                 return true;
7993
7994         // try center
7995         VectorCopy(eye, start);
7996         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7997         if (model->brush.TraceLineOfSight(model, start, end))
7998                 return true;
7999
8000         // try various random positions
8001         for (i = 0;i < numsamples;i++)
8002         {
8003                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8004                 if (model->brush.TraceLineOfSight(model, start, end))
8005                         return true;
8006         }
8007
8008         return false;
8009 }
8010
8011
8012 static void R_View_UpdateEntityVisible (void)
8013 {
8014         int i;
8015         int renderimask;
8016         int samples;
8017         entity_render_t *ent;
8018
8019         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8020                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8021                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8022                 :                                                          RENDER_EXTERIORMODEL;
8023         if (!r_drawviewmodel.integer)
8024                 renderimask |= RENDER_VIEWMODEL;
8025         if (!r_drawexteriormodel.integer)
8026                 renderimask |= RENDER_EXTERIORMODEL;
8027         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8028         {
8029                 // worldmodel can check visibility
8030                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8031                 for (i = 0;i < r_refdef.scene.numentities;i++)
8032                 {
8033                         ent = r_refdef.scene.entities[i];
8034                         if (!(ent->flags & renderimask))
8035                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8036                         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))
8037                                 r_refdef.viewcache.entityvisible[i] = true;
8038                 }
8039                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8040                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8041                 {
8042                         for (i = 0;i < r_refdef.scene.numentities;i++)
8043                         {
8044                                 ent = r_refdef.scene.entities[i];
8045                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8046                                 {
8047                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8048                                         if (samples < 0)
8049                                                 continue; // temp entities do pvs only
8050                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8051                                                 ent->last_trace_visibility = realtime;
8052                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8053                                                 r_refdef.viewcache.entityvisible[i] = 0;
8054                                 }
8055                         }
8056                 }
8057         }
8058         else
8059         {
8060                 // no worldmodel or it can't check visibility
8061                 for (i = 0;i < r_refdef.scene.numentities;i++)
8062                 {
8063                         ent = r_refdef.scene.entities[i];
8064                         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));
8065                 }
8066         }
8067 }
8068
8069 /// only used if skyrendermasked, and normally returns false
8070 int R_DrawBrushModelsSky (void)
8071 {
8072         int i, sky;
8073         entity_render_t *ent;
8074
8075         sky = false;
8076         for (i = 0;i < r_refdef.scene.numentities;i++)
8077         {
8078                 if (!r_refdef.viewcache.entityvisible[i])
8079                         continue;
8080                 ent = r_refdef.scene.entities[i];
8081                 if (!ent->model || !ent->model->DrawSky)
8082                         continue;
8083                 ent->model->DrawSky(ent);
8084                 sky = true;
8085         }
8086         return sky;
8087 }
8088
8089 static void R_DrawNoModel(entity_render_t *ent);
8090 static void R_DrawModels(void)
8091 {
8092         int i;
8093         entity_render_t *ent;
8094
8095         for (i = 0;i < r_refdef.scene.numentities;i++)
8096         {
8097                 if (!r_refdef.viewcache.entityvisible[i])
8098                         continue;
8099                 ent = r_refdef.scene.entities[i];
8100                 r_refdef.stats.entities++;
8101                 if (ent->model && ent->model->Draw != NULL)
8102                         ent->model->Draw(ent);
8103                 else
8104                         R_DrawNoModel(ent);
8105         }
8106 }
8107
8108 static void R_DrawModelsDepth(void)
8109 {
8110         int i;
8111         entity_render_t *ent;
8112
8113         for (i = 0;i < r_refdef.scene.numentities;i++)
8114         {
8115                 if (!r_refdef.viewcache.entityvisible[i])
8116                         continue;
8117                 ent = r_refdef.scene.entities[i];
8118                 if (ent->model && ent->model->DrawDepth != NULL)
8119                         ent->model->DrawDepth(ent);
8120         }
8121 }
8122
8123 static void R_DrawModelsDebug(void)
8124 {
8125         int i;
8126         entity_render_t *ent;
8127
8128         for (i = 0;i < r_refdef.scene.numentities;i++)
8129         {
8130                 if (!r_refdef.viewcache.entityvisible[i])
8131                         continue;
8132                 ent = r_refdef.scene.entities[i];
8133                 if (ent->model && ent->model->DrawDebug != NULL)
8134                         ent->model->DrawDebug(ent);
8135         }
8136 }
8137
8138 static void R_DrawModelsAddWaterPlanes(void)
8139 {
8140         int i;
8141         entity_render_t *ent;
8142
8143         for (i = 0;i < r_refdef.scene.numentities;i++)
8144         {
8145                 if (!r_refdef.viewcache.entityvisible[i])
8146                         continue;
8147                 ent = r_refdef.scene.entities[i];
8148                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8149                         ent->model->DrawAddWaterPlanes(ent);
8150         }
8151 }
8152
8153 static void R_View_SetFrustum(void)
8154 {
8155         int i;
8156         double slopex, slopey;
8157         vec3_t forward, left, up, origin;
8158
8159         // we can't trust r_refdef.view.forward and friends in reflected scenes
8160         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8161
8162 #if 0
8163         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8164         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8165         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8166         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8167         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8168         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8169         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8170         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8171         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8172         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8173         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8174         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8175 #endif
8176
8177 #if 0
8178         zNear = r_refdef.nearclip;
8179         nudge = 1.0 - 1.0 / (1<<23);
8180         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8181         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8182         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8183         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8184         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8185         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8186         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8187         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8188 #endif
8189
8190
8191
8192 #if 0
8193         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8194         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8195         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8196         r_refdef.view.frustum[0].dist = m[15] - m[12];
8197
8198         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8199         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8200         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8201         r_refdef.view.frustum[1].dist = m[15] + m[12];
8202
8203         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8204         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8205         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8206         r_refdef.view.frustum[2].dist = m[15] - m[13];
8207
8208         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8209         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8210         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8211         r_refdef.view.frustum[3].dist = m[15] + m[13];
8212
8213         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8214         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8215         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8216         r_refdef.view.frustum[4].dist = m[15] - m[14];
8217
8218         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8219         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8220         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8221         r_refdef.view.frustum[5].dist = m[15] + m[14];
8222 #endif
8223
8224         if (r_refdef.view.useperspective)
8225         {
8226                 slopex = 1.0 / r_refdef.view.frustum_x;
8227                 slopey = 1.0 / r_refdef.view.frustum_y;
8228                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8229                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8230                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8231                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8232                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8233
8234                 // Leaving those out was a mistake, those were in the old code, and they
8235                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8236                 // I couldn't reproduce it after adding those normalizations. --blub
8237                 VectorNormalize(r_refdef.view.frustum[0].normal);
8238                 VectorNormalize(r_refdef.view.frustum[1].normal);
8239                 VectorNormalize(r_refdef.view.frustum[2].normal);
8240                 VectorNormalize(r_refdef.view.frustum[3].normal);
8241
8242                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8243                 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]);
8244                 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]);
8245                 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]);
8246                 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]);
8247
8248                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8249                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8250                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8251                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8252                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8253         }
8254         else
8255         {
8256                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8257                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8258                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8259                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8260                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8261                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8262                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8263                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8264                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8265                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8266         }
8267         r_refdef.view.numfrustumplanes = 5;
8268
8269         if (r_refdef.view.useclipplane)
8270         {
8271                 r_refdef.view.numfrustumplanes = 6;
8272                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8273         }
8274
8275         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8276                 PlaneClassify(r_refdef.view.frustum + i);
8277
8278         // LordHavoc: note to all quake engine coders, Quake had a special case
8279         // for 90 degrees which assumed a square view (wrong), so I removed it,
8280         // Quake2 has it disabled as well.
8281
8282         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8283         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8284         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8285         //PlaneClassify(&frustum[0]);
8286
8287         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8288         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8289         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8290         //PlaneClassify(&frustum[1]);
8291
8292         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8293         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8294         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8295         //PlaneClassify(&frustum[2]);
8296
8297         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8298         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8299         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8300         //PlaneClassify(&frustum[3]);
8301
8302         // nearclip plane
8303         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8304         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8305         //PlaneClassify(&frustum[4]);
8306 }
8307
8308 void R_View_Update(void)
8309 {
8310         R_Main_ResizeViewCache();
8311         R_View_SetFrustum();
8312         R_View_WorldVisibility(r_refdef.view.useclipplane);
8313         R_View_UpdateEntityVisible();
8314         R_View_UpdateEntityLighting();
8315 }
8316
8317 void R_SetupView(qboolean allowwaterclippingplane)
8318 {
8319         const float *customclipplane = NULL;
8320         float plane[4];
8321         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8322         {
8323                 // LordHavoc: couldn't figure out how to make this approach the
8324                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8325                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8326                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8327                         dist = r_refdef.view.clipplane.dist;
8328                 plane[0] = r_refdef.view.clipplane.normal[0];
8329                 plane[1] = r_refdef.view.clipplane.normal[1];
8330                 plane[2] = r_refdef.view.clipplane.normal[2];
8331                 plane[3] = dist;
8332                 customclipplane = plane;
8333         }
8334
8335         if (!r_refdef.view.useperspective)
8336                 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);
8337         else if (vid.stencil && r_useinfinitefarclip.integer)
8338                 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);
8339         else
8340                 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);
8341         R_SetViewport(&r_refdef.view.viewport);
8342 }
8343
8344 void R_EntityMatrix(const matrix4x4_t *matrix)
8345 {
8346         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8347         {
8348                 gl_modelmatrixchanged = false;
8349                 gl_modelmatrix = *matrix;
8350                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8351                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8352                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8353                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8354                 CHECKGLERROR
8355                 switch(vid.renderpath)
8356                 {
8357                 case RENDERPATH_D3D9:
8358 #ifdef SUPPORTD3D
8359                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8360                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8361 #endif
8362                         break;
8363                 case RENDERPATH_D3D10:
8364                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8365                         break;
8366                 case RENDERPATH_D3D11:
8367                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8368                         break;
8369                 case RENDERPATH_GL20:
8370                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8371                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8372                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8373                         break;
8374                 case RENDERPATH_CGGL:
8375 #ifdef SUPPORTCG
8376                         CHECKCGERROR
8377                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8378                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8379                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8380 #endif
8381                         break;
8382                 case RENDERPATH_GL13:
8383                 case RENDERPATH_GL11:
8384                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8385                         break;
8386                 }
8387         }
8388 }
8389
8390 void R_ResetViewRendering2D(void)
8391 {
8392         r_viewport_t viewport;
8393         DrawQ_Finish();
8394
8395         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8396         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);
8397         R_SetViewport(&viewport);
8398         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8399         GL_Color(1, 1, 1, 1);
8400         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8401         GL_BlendFunc(GL_ONE, GL_ZERO);
8402         GL_AlphaTest(false);
8403         GL_ScissorTest(false);
8404         GL_DepthMask(false);
8405         GL_DepthRange(0, 1);
8406         GL_DepthTest(false);
8407         GL_DepthFunc(GL_LEQUAL);
8408         R_EntityMatrix(&identitymatrix);
8409         R_Mesh_ResetTextureState();
8410         GL_PolygonOffset(0, 0);
8411         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8412         switch(vid.renderpath)
8413         {
8414         case RENDERPATH_GL11:
8415         case RENDERPATH_GL13:
8416         case RENDERPATH_GL20:
8417         case RENDERPATH_CGGL:
8418                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8419                 break;
8420         case RENDERPATH_D3D9:
8421         case RENDERPATH_D3D10:
8422         case RENDERPATH_D3D11:
8423                 break;
8424         }
8425         GL_CullFace(GL_NONE);
8426 }
8427
8428 void R_ResetViewRendering3D(void)
8429 {
8430         DrawQ_Finish();
8431
8432         R_SetupView(true);
8433         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8434         GL_Color(1, 1, 1, 1);
8435         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8436         GL_BlendFunc(GL_ONE, GL_ZERO);
8437         GL_AlphaTest(false);
8438         GL_ScissorTest(true);
8439         GL_DepthMask(true);
8440         GL_DepthRange(0, 1);
8441         GL_DepthTest(true);
8442         GL_DepthFunc(GL_LEQUAL);
8443         R_EntityMatrix(&identitymatrix);
8444         R_Mesh_ResetTextureState();
8445         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8446         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8447         switch(vid.renderpath)
8448         {
8449         case RENDERPATH_GL11:
8450         case RENDERPATH_GL13:
8451         case RENDERPATH_GL20:
8452         case RENDERPATH_CGGL:
8453                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8454                 break;
8455         case RENDERPATH_D3D9:
8456         case RENDERPATH_D3D10:
8457         case RENDERPATH_D3D11:
8458                 break;
8459         }
8460         GL_CullFace(r_refdef.view.cullface_back);
8461 }
8462
8463 /*
8464 ================
8465 R_RenderView_UpdateViewVectors
8466 ================
8467 */
8468 static void R_RenderView_UpdateViewVectors(void)
8469 {
8470         // break apart the view matrix into vectors for various purposes
8471         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8472         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8473         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8474         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8475         // make an inverted copy of the view matrix for tracking sprites
8476         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8477 }
8478
8479 void R_RenderScene(void);
8480 void R_RenderWaterPlanes(void);
8481
8482 static void R_Water_StartFrame(void)
8483 {
8484         int i;
8485         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8486         r_waterstate_waterplane_t *p;
8487
8488         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8489                 return;
8490
8491         switch(vid.renderpath)
8492         {
8493         case RENDERPATH_GL20:
8494         case RENDERPATH_CGGL:
8495         case RENDERPATH_D3D9:
8496         case RENDERPATH_D3D10:
8497         case RENDERPATH_D3D11:
8498                 break;
8499         case RENDERPATH_GL13:
8500         case RENDERPATH_GL11:
8501                 return;
8502         }
8503
8504         // set waterwidth and waterheight to the water resolution that will be
8505         // used (often less than the screen resolution for faster rendering)
8506         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8507         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8508
8509         // calculate desired texture sizes
8510         // can't use water if the card does not support the texture size
8511         if (!r_water.integer || r_showsurfaces.integer)
8512                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8513         else if (vid.support.arb_texture_non_power_of_two)
8514         {
8515                 texturewidth = waterwidth;
8516                 textureheight = waterheight;
8517                 camerawidth = waterwidth;
8518                 cameraheight = waterheight;
8519         }
8520         else
8521         {
8522                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8523                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8524                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8525                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8526         }
8527
8528         // allocate textures as needed
8529         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8530         {
8531                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8532                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8533                 {
8534                         if (p->texture_refraction)
8535                                 R_FreeTexture(p->texture_refraction);
8536                         p->texture_refraction = NULL;
8537                         if (p->texture_reflection)
8538                                 R_FreeTexture(p->texture_reflection);
8539                         p->texture_reflection = NULL;
8540                         if (p->texture_camera)
8541                                 R_FreeTexture(p->texture_camera);
8542                         p->texture_camera = NULL;
8543                 }
8544                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8545                 r_waterstate.texturewidth = texturewidth;
8546                 r_waterstate.textureheight = textureheight;
8547                 r_waterstate.camerawidth = camerawidth;
8548                 r_waterstate.cameraheight = cameraheight;
8549         }
8550
8551         if (r_waterstate.texturewidth)
8552         {
8553                 r_waterstate.enabled = true;
8554
8555                 // when doing a reduced render (HDR) we want to use a smaller area
8556                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8557                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8558
8559                 // set up variables that will be used in shader setup
8560                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8561                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8562                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8563                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8564         }
8565
8566         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8567         r_waterstate.numwaterplanes = 0;
8568 }
8569
8570 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8571 {
8572         int triangleindex, planeindex;
8573         const int *e;
8574         vec3_t vert[3];
8575         vec3_t normal;
8576         vec3_t center;
8577         mplane_t plane;
8578         int cam_ent;
8579         r_waterstate_waterplane_t *p;
8580         texture_t *t = R_GetCurrentTexture(surface->texture);
8581         cam_ent = t->camera_entity;
8582         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8583                 cam_ent = 0;
8584
8585         // just use the first triangle with a valid normal for any decisions
8586         VectorClear(normal);
8587         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8588         {
8589                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8590                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8591                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8592                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8593                 if (VectorLength2(normal) >= 0.001)
8594                         break;
8595         }
8596
8597         VectorCopy(normal, plane.normal);
8598         VectorNormalize(plane.normal);
8599         plane.dist = DotProduct(vert[0], plane.normal);
8600         PlaneClassify(&plane);
8601         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8602         {
8603                 // skip backfaces (except if nocullface is set)
8604                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8605                         return;
8606                 VectorNegate(plane.normal, plane.normal);
8607                 plane.dist *= -1;
8608                 PlaneClassify(&plane);
8609         }
8610
8611
8612         // find a matching plane if there is one
8613         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8614                 if(p->camera_entity == t->camera_entity)
8615                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8616                                 break;
8617         if (planeindex >= r_waterstate.maxwaterplanes)
8618                 return; // nothing we can do, out of planes
8619
8620         // if this triangle does not fit any known plane rendered this frame, add one
8621         if (planeindex >= r_waterstate.numwaterplanes)
8622         {
8623                 // store the new plane
8624                 r_waterstate.numwaterplanes++;
8625                 p->plane = plane;
8626                 // clear materialflags and pvs
8627                 p->materialflags = 0;
8628                 p->pvsvalid = false;
8629                 p->camera_entity = t->camera_entity;
8630         }
8631         // merge this surface's materialflags into the waterplane
8632         p->materialflags |= t->currentmaterialflags;
8633         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8634         {
8635                 // merge this surface's PVS into the waterplane
8636                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8637                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8638                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8639                 {
8640                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8641                         p->pvsvalid = true;
8642                 }
8643         }
8644 }
8645
8646 static void R_Water_ProcessPlanes(void)
8647 {
8648         r_refdef_view_t originalview;
8649         r_refdef_view_t myview;
8650         int planeindex;
8651         r_waterstate_waterplane_t *p;
8652         vec3_t visorigin;
8653
8654         originalview = r_refdef.view;
8655
8656         // make sure enough textures are allocated
8657         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8658         {
8659                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8660                 {
8661                         if (!p->texture_refraction)
8662                                 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);
8663                         if (!p->texture_refraction)
8664                                 goto error;
8665                 }
8666                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8667                 {
8668                         if (!p->texture_camera)
8669                                 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);
8670                         if (!p->texture_camera)
8671                                 goto error;
8672                 }
8673
8674                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8675                 {
8676                         if (!p->texture_reflection)
8677                                 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);
8678                         if (!p->texture_reflection)
8679                                 goto error;
8680                 }
8681         }
8682
8683         // render views
8684         r_refdef.view = originalview;
8685         r_refdef.view.showdebug = false;
8686         r_refdef.view.width = r_waterstate.waterwidth;
8687         r_refdef.view.height = r_waterstate.waterheight;
8688         r_refdef.view.useclipplane = true;
8689         myview = r_refdef.view;
8690         r_waterstate.renderingscene = true;
8691         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8692         {
8693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8694                 {
8695                         r_refdef.view = myview;
8696                         // render reflected scene and copy into texture
8697                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8698                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8699                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8700                         r_refdef.view.clipplane = p->plane;
8701                         // reverse the cullface settings for this render
8702                         r_refdef.view.cullface_front = GL_FRONT;
8703                         r_refdef.view.cullface_back = GL_BACK;
8704                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8705                         {
8706                                 r_refdef.view.usecustompvs = true;
8707                                 if (p->pvsvalid)
8708                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8709                                 else
8710                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8711                         }
8712
8713                         R_ResetViewRendering3D();
8714                         R_ClearScreen(r_refdef.fogenabled);
8715                         R_View_Update();
8716                         R_RenderScene();
8717
8718                         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);
8719                 }
8720
8721                 // render the normal view scene and copy into texture
8722                 // (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)
8723                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8724                 {
8725                         r_waterstate.renderingrefraction = true;
8726                         r_refdef.view = myview;
8727
8728                         r_refdef.view.clipplane = p->plane;
8729                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8730                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8731
8732                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8733                         {
8734                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8735                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8736                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8737                                 R_RenderView_UpdateViewVectors();
8738                                 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);
8739                         }
8740
8741                         PlaneClassify(&r_refdef.view.clipplane);
8742
8743                         R_ResetViewRendering3D();
8744                         R_ClearScreen(r_refdef.fogenabled);
8745                         R_View_Update();
8746                         R_RenderScene();
8747
8748                         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);
8749                         r_waterstate.renderingrefraction = false;
8750                 }
8751                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8752                 {
8753                         r_refdef.view = myview;
8754
8755                         r_refdef.view.clipplane = p->plane;
8756                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8757                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8758
8759                         r_refdef.view.width = r_waterstate.camerawidth;
8760                         r_refdef.view.height = r_waterstate.cameraheight;
8761                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8762                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8763
8764                         if(p->camera_entity)
8765                         {
8766                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8767                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8768                         }
8769
8770                         // reverse the cullface settings for this render
8771                         r_refdef.view.cullface_front = GL_FRONT;
8772                         r_refdef.view.cullface_back = GL_BACK;
8773                         // also reverse the view matrix
8774                         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
8775                         R_RenderView_UpdateViewVectors();
8776                         if(p->camera_entity)
8777                                 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);
8778                         
8779                         // camera needs no clipplane
8780                         r_refdef.view.useclipplane = false;
8781
8782                         PlaneClassify(&r_refdef.view.clipplane);
8783
8784                         R_ResetViewRendering3D();
8785                         R_ClearScreen(r_refdef.fogenabled);
8786                         R_View_Update();
8787                         R_RenderScene();
8788
8789                         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);
8790                         r_waterstate.renderingrefraction = false;
8791                 }
8792
8793         }
8794         r_waterstate.renderingscene = false;
8795         r_refdef.view = originalview;
8796         R_ResetViewRendering3D();
8797         R_ClearScreen(r_refdef.fogenabled);
8798         R_View_Update();
8799         return;
8800 error:
8801         r_refdef.view = originalview;
8802         r_waterstate.renderingscene = false;
8803         Cvar_SetValueQuick(&r_water, 0);
8804         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8805         return;
8806 }
8807
8808 void R_Bloom_StartFrame(void)
8809 {
8810         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8811
8812         switch(vid.renderpath)
8813         {
8814         case RENDERPATH_GL20:
8815         case RENDERPATH_CGGL:
8816         case RENDERPATH_D3D9:
8817         case RENDERPATH_D3D10:
8818         case RENDERPATH_D3D11:
8819                 break;
8820         case RENDERPATH_GL13:
8821         case RENDERPATH_GL11:
8822                 return;
8823         }
8824
8825         // set bloomwidth and bloomheight to the bloom resolution that will be
8826         // used (often less than the screen resolution for faster rendering)
8827         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8828         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8829         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8830         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8831         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8832
8833         // calculate desired texture sizes
8834         if (vid.support.arb_texture_non_power_of_two)
8835         {
8836                 screentexturewidth = r_refdef.view.width;
8837                 screentextureheight = r_refdef.view.height;
8838                 bloomtexturewidth = r_bloomstate.bloomwidth;
8839                 bloomtextureheight = r_bloomstate.bloomheight;
8840         }
8841         else
8842         {
8843                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8844                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8845                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8846                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8847         }
8848
8849         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))
8850         {
8851                 Cvar_SetValueQuick(&r_hdr, 0);
8852                 Cvar_SetValueQuick(&r_bloom, 0);
8853                 Cvar_SetValueQuick(&r_motionblur, 0);
8854                 Cvar_SetValueQuick(&r_damageblur, 0);
8855         }
8856
8857         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)))
8858                 screentexturewidth = screentextureheight = 0;
8859         if (!r_hdr.integer && !r_bloom.integer)
8860                 bloomtexturewidth = bloomtextureheight = 0;
8861
8862         // allocate textures as needed
8863         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8864         {
8865                 if (r_bloomstate.texture_screen)
8866                         R_FreeTexture(r_bloomstate.texture_screen);
8867                 r_bloomstate.texture_screen = NULL;
8868                 r_bloomstate.screentexturewidth = screentexturewidth;
8869                 r_bloomstate.screentextureheight = screentextureheight;
8870                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8871                         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);
8872         }
8873         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8874         {
8875                 if (r_bloomstate.texture_bloom)
8876                         R_FreeTexture(r_bloomstate.texture_bloom);
8877                 r_bloomstate.texture_bloom = NULL;
8878                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8879                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8880                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8881                         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);
8882         }
8883
8884         // when doing a reduced render (HDR) we want to use a smaller area
8885         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8886         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8887         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8888         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8889         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8890
8891         // set up a texcoord array for the full resolution screen image
8892         // (we have to keep this around to copy back during final render)
8893         r_bloomstate.screentexcoord2f[0] = 0;
8894         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8895         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8896         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8897         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8898         r_bloomstate.screentexcoord2f[5] = 0;
8899         r_bloomstate.screentexcoord2f[6] = 0;
8900         r_bloomstate.screentexcoord2f[7] = 0;
8901
8902         // set up a texcoord array for the reduced resolution bloom image
8903         // (which will be additive blended over the screen image)
8904         r_bloomstate.bloomtexcoord2f[0] = 0;
8905         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8906         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8907         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8908         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8909         r_bloomstate.bloomtexcoord2f[5] = 0;
8910         r_bloomstate.bloomtexcoord2f[6] = 0;
8911         r_bloomstate.bloomtexcoord2f[7] = 0;
8912
8913         switch(vid.renderpath)
8914         {
8915         case RENDERPATH_GL11:
8916         case RENDERPATH_GL13:
8917         case RENDERPATH_GL20:
8918         case RENDERPATH_CGGL:
8919                 break;
8920         case RENDERPATH_D3D9:
8921         case RENDERPATH_D3D10:
8922         case RENDERPATH_D3D11:
8923                 {
8924                         int i;
8925                         for (i = 0;i < 4;i++)
8926                         {
8927                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8928                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8929                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8930                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8931                         }
8932                 }
8933                 break;
8934         }
8935
8936         if (r_hdr.integer || r_bloom.integer)
8937         {
8938                 r_bloomstate.enabled = true;
8939                 r_bloomstate.hdr = r_hdr.integer != 0;
8940         }
8941
8942         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);
8943 }
8944
8945 void R_Bloom_CopyBloomTexture(float colorscale)
8946 {
8947         r_refdef.stats.bloom++;
8948
8949         // scale down screen texture to the bloom texture size
8950         CHECKGLERROR
8951         R_SetViewport(&r_bloomstate.viewport);
8952         GL_BlendFunc(GL_ONE, GL_ZERO);
8953         GL_Color(colorscale, colorscale, colorscale, 1);
8954         // 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...
8955         switch(vid.renderpath)
8956         {
8957         case RENDERPATH_GL11:
8958         case RENDERPATH_GL13:
8959         case RENDERPATH_GL20:
8960         case RENDERPATH_CGGL:
8961                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8962                 break;
8963         case RENDERPATH_D3D9:
8964         case RENDERPATH_D3D10:
8965         case RENDERPATH_D3D11:
8966                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8967                 break;
8968         }
8969         // TODO: do boxfilter scale-down in shader?
8970         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8971         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8972         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8973
8974         // we now have a bloom image in the framebuffer
8975         // copy it into the bloom image texture for later processing
8976         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8977         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8978 }
8979
8980 void R_Bloom_CopyHDRTexture(void)
8981 {
8982         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);
8983         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8984 }
8985
8986 void R_Bloom_MakeTexture(void)
8987 {
8988         int x, range, dir;
8989         float xoffset, yoffset, r, brighten;
8990
8991         r_refdef.stats.bloom++;
8992
8993         R_ResetViewRendering2D();
8994
8995         // we have a bloom image in the framebuffer
8996         CHECKGLERROR
8997         R_SetViewport(&r_bloomstate.viewport);
8998
8999         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9000         {
9001                 x *= 2;
9002                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9003                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9004                 GL_Color(r,r,r,1);
9005                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9006                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9007                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9008                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9009
9010                 // copy the vertically blurred bloom view to a texture
9011                 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);
9012                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9013         }
9014
9015         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9016         brighten = r_bloom_brighten.value;
9017         if (r_hdr.integer)
9018                 brighten *= r_hdr_range.value;
9019         brighten = sqrt(brighten);
9020         if(range >= 1)
9021                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9022         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9023
9024         for (dir = 0;dir < 2;dir++)
9025         {
9026                 // blend on at multiple vertical offsets to achieve a vertical blur
9027                 // TODO: do offset blends using GLSL
9028                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9029                 GL_BlendFunc(GL_ONE, GL_ZERO);
9030                 for (x = -range;x <= range;x++)
9031                 {
9032                         if (!dir){xoffset = 0;yoffset = x;}
9033                         else {xoffset = x;yoffset = 0;}
9034                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9035                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9036                         // compute a texcoord array with the specified x and y offset
9037                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9038                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9039                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9040                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9041                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9042                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9043                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9044                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9045                         // this r value looks like a 'dot' particle, fading sharply to
9046                         // black at the edges
9047                         // (probably not realistic but looks good enough)
9048                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9049                         //r = brighten/(range*2+1);
9050                         r = brighten / (range * 2 + 1);
9051                         if(range >= 1)
9052                                 r *= (1 - x*x/(float)(range*range));
9053                         GL_Color(r, r, r, 1);
9054                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9055                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9056                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9057                         GL_BlendFunc(GL_ONE, GL_ONE);
9058                 }
9059
9060                 // copy the vertically blurred bloom view to a texture
9061                 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);
9062                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9063         }
9064 }
9065
9066 void R_HDR_RenderBloomTexture(void)
9067 {
9068         int oldwidth, oldheight;
9069         float oldcolorscale;
9070
9071         oldcolorscale = r_refdef.view.colorscale;
9072         oldwidth = r_refdef.view.width;
9073         oldheight = r_refdef.view.height;
9074         r_refdef.view.width = r_bloomstate.bloomwidth;
9075         r_refdef.view.height = r_bloomstate.bloomheight;
9076
9077         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9078         // TODO: add exposure compensation features
9079         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9080
9081         r_refdef.view.showdebug = false;
9082         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9083
9084         R_ResetViewRendering3D();
9085
9086         R_ClearScreen(r_refdef.fogenabled);
9087         if (r_timereport_active)
9088                 R_TimeReport("HDRclear");
9089
9090         R_View_Update();
9091         if (r_timereport_active)
9092                 R_TimeReport("visibility");
9093
9094         // only do secondary renders with HDR if r_hdr is 2 or higher
9095         r_waterstate.numwaterplanes = 0;
9096         if (r_waterstate.enabled && r_hdr.integer >= 2)
9097                 R_RenderWaterPlanes();
9098
9099         r_refdef.view.showdebug = true;
9100         R_RenderScene();
9101         r_waterstate.numwaterplanes = 0;
9102
9103         R_ResetViewRendering2D();
9104
9105         R_Bloom_CopyHDRTexture();
9106         R_Bloom_MakeTexture();
9107
9108         // restore the view settings
9109         r_refdef.view.width = oldwidth;
9110         r_refdef.view.height = oldheight;
9111         r_refdef.view.colorscale = oldcolorscale;
9112
9113         R_ResetViewRendering3D();
9114
9115         R_ClearScreen(r_refdef.fogenabled);
9116         if (r_timereport_active)
9117                 R_TimeReport("viewclear");
9118 }
9119
9120 static void R_BlendView(void)
9121 {
9122         unsigned int permutation;
9123         float uservecs[4][4];
9124
9125         switch (vid.renderpath)
9126         {
9127         case RENDERPATH_GL20:
9128         case RENDERPATH_CGGL:
9129         case RENDERPATH_D3D9:
9130         case RENDERPATH_D3D10:
9131         case RENDERPATH_D3D11:
9132                 permutation =
9133                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9134                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9135                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9136                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9137                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9138
9139                 if (r_bloomstate.texture_screen)
9140                 {
9141                         // make sure the buffer is available
9142                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9143
9144                         R_ResetViewRendering2D();
9145
9146                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9147                         {
9148                                 // declare variables
9149                                 float speed;
9150                                 static float avgspeed;
9151
9152                                 speed = VectorLength(cl.movement_velocity);
9153
9154                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9155                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9156
9157                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9158                                 speed = bound(0, speed, 1);
9159                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9160
9161                                 // calculate values into a standard alpha
9162                                 cl.motionbluralpha = 1 - exp(-
9163                                                 (
9164                                                  (r_motionblur.value * speed / 80)
9165                                                  +
9166                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9167                                                 )
9168                                                 /
9169                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9170                                            );
9171
9172                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9173                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9174                                 // apply the blur
9175                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9176                                 {
9177                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9178                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9179                                         switch(vid.renderpath)
9180                                         {
9181                                         case RENDERPATH_GL11:
9182                                         case RENDERPATH_GL13:
9183                                         case RENDERPATH_GL20:
9184                                         case RENDERPATH_CGGL:
9185                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9186                                                 break;
9187                                         case RENDERPATH_D3D9:
9188                                         case RENDERPATH_D3D10:
9189                                         case RENDERPATH_D3D11:
9190                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9191                                                 break;
9192                                         }
9193                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9194                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9195                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9196                                 }
9197                         }
9198
9199                         // copy view into the screen texture
9200                         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);
9201                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9202                 }
9203                 else if (!r_bloomstate.texture_bloom)
9204                 {
9205                         // we may still have to do view tint...
9206                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9207                         {
9208                                 // apply a color tint to the whole view
9209                                 R_ResetViewRendering2D();
9210                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9211                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9212                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9213                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9214                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9215                         }
9216                         break; // no screen processing, no bloom, skip it
9217                 }
9218
9219                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9220                 {
9221                         // render simple bloom effect
9222                         // copy the screen and shrink it and darken it for the bloom process
9223                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9224                         // make the bloom texture
9225                         R_Bloom_MakeTexture();
9226                 }
9227
9228 #if _MSC_VER >= 1400
9229 #define sscanf sscanf_s
9230 #endif
9231                 memset(uservecs, 0, sizeof(uservecs));
9232                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9233                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9234                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9235                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9236
9237                 R_ResetViewRendering2D();
9238                 GL_Color(1, 1, 1, 1);
9239                 GL_BlendFunc(GL_ONE, GL_ZERO);
9240
9241                 switch(vid.renderpath)
9242                 {
9243                 case RENDERPATH_GL20:
9244                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9245                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9246                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9247                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9248                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9249                         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]);
9250                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9251                         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]);
9252                         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]);
9253                         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]);
9254                         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]);
9255                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9256                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9257                         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);
9258                         break;
9259                 case RENDERPATH_CGGL:
9260 #ifdef SUPPORTCG
9261                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9262                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9263                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9264                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9265                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9266                         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
9267                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9268                         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
9269                         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
9270                         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
9271                         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
9272                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9273                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9274                         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);
9275 #endif
9276                         break;
9277                 case RENDERPATH_D3D9:
9278 #ifdef SUPPORTD3D
9279                         // 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...
9280                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9281                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9282                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9283                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9284                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9285                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9286                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9287                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9288                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9289                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9290                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9291                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9292                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9293                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9294 #endif
9295                         break;
9296                 case RENDERPATH_D3D10:
9297                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9298                         break;
9299                 case RENDERPATH_D3D11:
9300                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9301                         break;
9302                 default:
9303                         break;
9304                 }
9305                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9306                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9307                 break;
9308         case RENDERPATH_GL13:
9309         case RENDERPATH_GL11:
9310                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9311                 {
9312                         // apply a color tint to the whole view
9313                         R_ResetViewRendering2D();
9314                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9315                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9316                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9317                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9318                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9319                 }
9320                 break;
9321         }
9322 }
9323
9324 matrix4x4_t r_waterscrollmatrix;
9325
9326 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9327 {
9328         if (r_refdef.fog_density)
9329         {
9330                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9331                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9332                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9333
9334                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9335                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9336                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9337                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9338
9339                 {
9340                         vec3_t fogvec;
9341                         VectorCopy(r_refdef.fogcolor, fogvec);
9342                         //   color.rgb *= ContrastBoost * SceneBrightness;
9343                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9344                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9345                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9346                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9347                 }
9348         }
9349 }
9350
9351 void R_UpdateVariables(void)
9352 {
9353         R_Textures_Frame();
9354
9355         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9356
9357         r_refdef.farclip = r_farclip_base.value;
9358         if (r_refdef.scene.worldmodel)
9359                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9360         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9361
9362         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9363                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9364         r_refdef.polygonfactor = 0;
9365         r_refdef.polygonoffset = 0;
9366         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9367         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9368
9369         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9370         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9371         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9372         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9373         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9374         if (r_showsurfaces.integer)
9375         {
9376                 r_refdef.scene.rtworld = false;
9377                 r_refdef.scene.rtworldshadows = false;
9378                 r_refdef.scene.rtdlight = false;
9379                 r_refdef.scene.rtdlightshadows = false;
9380                 r_refdef.lightmapintensity = 0;
9381         }
9382
9383         if (gamemode == GAME_NEHAHRA)
9384         {
9385                 if (gl_fogenable.integer)
9386                 {
9387                         r_refdef.oldgl_fogenable = true;
9388                         r_refdef.fog_density = gl_fogdensity.value;
9389                         r_refdef.fog_red = gl_fogred.value;
9390                         r_refdef.fog_green = gl_foggreen.value;
9391                         r_refdef.fog_blue = gl_fogblue.value;
9392                         r_refdef.fog_alpha = 1;
9393                         r_refdef.fog_start = 0;
9394                         r_refdef.fog_end = gl_skyclip.value;
9395                         r_refdef.fog_height = 1<<30;
9396                         r_refdef.fog_fadedepth = 128;
9397                 }
9398                 else if (r_refdef.oldgl_fogenable)
9399                 {
9400                         r_refdef.oldgl_fogenable = false;
9401                         r_refdef.fog_density = 0;
9402                         r_refdef.fog_red = 0;
9403                         r_refdef.fog_green = 0;
9404                         r_refdef.fog_blue = 0;
9405                         r_refdef.fog_alpha = 0;
9406                         r_refdef.fog_start = 0;
9407                         r_refdef.fog_end = 0;
9408                         r_refdef.fog_height = 1<<30;
9409                         r_refdef.fog_fadedepth = 128;
9410                 }
9411         }
9412
9413         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9414         r_refdef.fog_start = max(0, r_refdef.fog_start);
9415         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9416
9417         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9418
9419         if (r_refdef.fog_density && r_drawfog.integer)
9420         {
9421                 r_refdef.fogenabled = true;
9422                 // this is the point where the fog reaches 0.9986 alpha, which we
9423                 // consider a good enough cutoff point for the texture
9424                 // (0.9986 * 256 == 255.6)
9425                 if (r_fog_exp2.integer)
9426                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9427                 else
9428                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9429                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9430                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9431                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9432                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9433                         R_BuildFogHeightTexture();
9434                 // fog color was already set
9435                 // update the fog texture
9436                 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)
9437                         R_BuildFogTexture();
9438                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9439                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9440         }
9441         else
9442                 r_refdef.fogenabled = false;
9443
9444         switch(vid.renderpath)
9445         {
9446         case RENDERPATH_GL20:
9447         case RENDERPATH_CGGL:
9448         case RENDERPATH_D3D9:
9449         case RENDERPATH_D3D10:
9450         case RENDERPATH_D3D11:
9451                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9452                 {
9453                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9454                         {
9455                                 // build GLSL gamma texture
9456 #define RAMPWIDTH 256
9457                                 unsigned short ramp[RAMPWIDTH * 3];
9458                                 unsigned char rampbgr[RAMPWIDTH][4];
9459                                 int i;
9460
9461                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9462
9463                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9464                                 for(i = 0; i < RAMPWIDTH; ++i)
9465                                 {
9466                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9467                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9468                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9469                                         rampbgr[i][3] = 0;
9470                                 }
9471                                 if (r_texture_gammaramps)
9472                                 {
9473                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9474                                 }
9475                                 else
9476                                 {
9477                                         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);
9478                                 }
9479                         }
9480                 }
9481                 else
9482                 {
9483                         // remove GLSL gamma texture
9484                 }
9485                 break;
9486         case RENDERPATH_GL13:
9487         case RENDERPATH_GL11:
9488                 break;
9489         }
9490 }
9491
9492 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9493 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9494 /*
9495 ================
9496 R_SelectScene
9497 ================
9498 */
9499 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9500         if( scenetype != r_currentscenetype ) {
9501                 // store the old scenetype
9502                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9503                 r_currentscenetype = scenetype;
9504                 // move in the new scene
9505                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9506         }
9507 }
9508
9509 /*
9510 ================
9511 R_GetScenePointer
9512 ================
9513 */
9514 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9515 {
9516         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9517         if( scenetype == r_currentscenetype ) {
9518                 return &r_refdef.scene;
9519         } else {
9520                 return &r_scenes_store[ scenetype ];
9521         }
9522 }
9523
9524 /*
9525 ================
9526 R_RenderView
9527 ================
9528 */
9529 void R_RenderView(void)
9530 {
9531         if (r_timereport_active)
9532                 R_TimeReport("start");
9533         r_textureframe++; // used only by R_GetCurrentTexture
9534         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9535
9536         if (!r_drawentities.integer)
9537                 r_refdef.scene.numentities = 0;
9538
9539         R_AnimCache_ClearCache();
9540         R_FrameData_NewFrame();
9541
9542         if (r_refdef.view.isoverlay)
9543         {
9544                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9545                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9546                 R_TimeReport("depthclear");
9547
9548                 r_refdef.view.showdebug = false;
9549
9550                 r_waterstate.enabled = false;
9551                 r_waterstate.numwaterplanes = 0;
9552
9553                 R_RenderScene();
9554
9555                 CHECKGLERROR
9556                 return;
9557         }
9558
9559         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9560                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9561
9562         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9563
9564         R_RenderView_UpdateViewVectors();
9565
9566         R_Shadow_UpdateWorldLightSelection();
9567
9568         R_Bloom_StartFrame();
9569         R_Water_StartFrame();
9570
9571         CHECKGLERROR
9572         if (r_timereport_active)
9573                 R_TimeReport("viewsetup");
9574
9575         R_ResetViewRendering3D();
9576
9577         if (r_refdef.view.clear || r_refdef.fogenabled)
9578         {
9579                 R_ClearScreen(r_refdef.fogenabled);
9580                 if (r_timereport_active)
9581                         R_TimeReport("viewclear");
9582         }
9583         r_refdef.view.clear = true;
9584
9585         // this produces a bloom texture to be used in R_BlendView() later
9586         if (r_hdr.integer && r_bloomstate.bloomwidth)
9587         {
9588                 R_HDR_RenderBloomTexture();
9589                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9590                 r_textureframe++; // used only by R_GetCurrentTexture
9591         }
9592
9593         r_refdef.view.showdebug = true;
9594
9595         R_View_Update();
9596         if (r_timereport_active)
9597                 R_TimeReport("visibility");
9598
9599         r_waterstate.numwaterplanes = 0;
9600         if (r_waterstate.enabled)
9601                 R_RenderWaterPlanes();
9602
9603         R_RenderScene();
9604         r_waterstate.numwaterplanes = 0;
9605
9606         R_BlendView();
9607         if (r_timereport_active)
9608                 R_TimeReport("blendview");
9609
9610         GL_Scissor(0, 0, vid.width, vid.height);
9611         GL_ScissorTest(false);
9612         CHECKGLERROR
9613 }
9614
9615 void R_RenderWaterPlanes(void)
9616 {
9617         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9618         {
9619                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9620                 if (r_timereport_active)
9621                         R_TimeReport("waterworld");
9622         }
9623
9624         // don't let sound skip if going slow
9625         if (r_refdef.scene.extraupdate)
9626                 S_ExtraUpdate ();
9627
9628         R_DrawModelsAddWaterPlanes();
9629         if (r_timereport_active)
9630                 R_TimeReport("watermodels");
9631
9632         if (r_waterstate.numwaterplanes)
9633         {
9634                 R_Water_ProcessPlanes();
9635                 if (r_timereport_active)
9636                         R_TimeReport("waterscenes");
9637         }
9638 }
9639
9640 extern void R_DrawLightningBeams (void);
9641 extern void VM_CL_AddPolygonsToMeshQueue (void);
9642 extern void R_DrawPortals (void);
9643 extern cvar_t cl_locs_show;
9644 static void R_DrawLocs(void);
9645 static void R_DrawEntityBBoxes(void);
9646 static void R_DrawModelDecals(void);
9647 extern void R_DrawModelShadows(void);
9648 extern void R_DrawModelShadowMaps(void);
9649 extern cvar_t cl_decals_newsystem;
9650 extern qboolean r_shadow_usingdeferredprepass;
9651 void R_RenderScene(void)
9652 {
9653         qboolean shadowmapping = false;
9654
9655         if (r_timereport_active)
9656                 R_TimeReport("beginscene");
9657
9658         r_refdef.stats.renders++;
9659
9660         R_UpdateFogColor();
9661
9662         // don't let sound skip if going slow
9663         if (r_refdef.scene.extraupdate)
9664                 S_ExtraUpdate ();
9665
9666         R_MeshQueue_BeginScene();
9667
9668         R_SkyStartFrame();
9669
9670         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);
9671
9672         if (r_timereport_active)
9673                 R_TimeReport("skystartframe");
9674
9675         if (cl.csqc_vidvars.drawworld)
9676         {
9677                 // don't let sound skip if going slow
9678                 if (r_refdef.scene.extraupdate)
9679                         S_ExtraUpdate ();
9680
9681                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9682                 {
9683                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9684                         if (r_timereport_active)
9685                                 R_TimeReport("worldsky");
9686                 }
9687
9688                 if (R_DrawBrushModelsSky() && r_timereport_active)
9689                         R_TimeReport("bmodelsky");
9690
9691                 if (skyrendermasked && skyrenderlater)
9692                 {
9693                         // we have to force off the water clipping plane while rendering sky
9694                         R_SetupView(false);
9695                         R_Sky();
9696                         R_SetupView(true);
9697                         if (r_timereport_active)
9698                                 R_TimeReport("sky");
9699                 }
9700         }
9701
9702         R_AnimCache_CacheVisibleEntities();
9703         if (r_timereport_active)
9704                 R_TimeReport("animation");
9705
9706         R_Shadow_PrepareLights();
9707         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9708                 R_Shadow_PrepareModelShadows();
9709         if (r_timereport_active)
9710                 R_TimeReport("preparelights");
9711
9712         if (R_Shadow_ShadowMappingEnabled())
9713                 shadowmapping = true;
9714
9715         if (r_shadow_usingdeferredprepass)
9716                 R_Shadow_DrawPrepass();
9717
9718         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9719         {
9720                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9721                 if (r_timereport_active)
9722                         R_TimeReport("worlddepth");
9723         }
9724         if (r_depthfirst.integer >= 2)
9725         {
9726                 R_DrawModelsDepth();
9727                 if (r_timereport_active)
9728                         R_TimeReport("modeldepth");
9729         }
9730
9731         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9732         {
9733                 R_DrawModelShadowMaps();
9734                 R_ResetViewRendering3D();
9735                 // don't let sound skip if going slow
9736                 if (r_refdef.scene.extraupdate)
9737                         S_ExtraUpdate ();
9738         }
9739
9740         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9741         {
9742                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9743                 if (r_timereport_active)
9744                         R_TimeReport("world");
9745         }
9746
9747         // don't let sound skip if going slow
9748         if (r_refdef.scene.extraupdate)
9749                 S_ExtraUpdate ();
9750
9751         R_DrawModels();
9752         if (r_timereport_active)
9753                 R_TimeReport("models");
9754
9755         // don't let sound skip if going slow
9756         if (r_refdef.scene.extraupdate)
9757                 S_ExtraUpdate ();
9758
9759         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9760         {
9761                 R_DrawModelShadows();
9762                 R_ResetViewRendering3D();
9763                 // don't let sound skip if going slow
9764                 if (r_refdef.scene.extraupdate)
9765                         S_ExtraUpdate ();
9766         }
9767
9768         if (!r_shadow_usingdeferredprepass)
9769         {
9770                 R_Shadow_DrawLights();
9771                 if (r_timereport_active)
9772                         R_TimeReport("rtlights");
9773         }
9774
9775         // don't let sound skip if going slow
9776         if (r_refdef.scene.extraupdate)
9777                 S_ExtraUpdate ();
9778
9779         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9780         {
9781                 R_DrawModelShadows();
9782                 R_ResetViewRendering3D();
9783                 // don't let sound skip if going slow
9784                 if (r_refdef.scene.extraupdate)
9785                         S_ExtraUpdate ();
9786         }
9787
9788         if (cl.csqc_vidvars.drawworld)
9789         {
9790                 if (cl_decals_newsystem.integer)
9791                 {
9792                         R_DrawModelDecals();
9793                         if (r_timereport_active)
9794                                 R_TimeReport("modeldecals");
9795                 }
9796                 else
9797                 {
9798                         R_DrawDecals();
9799                         if (r_timereport_active)
9800                                 R_TimeReport("decals");
9801                 }
9802
9803                 R_DrawParticles();
9804                 if (r_timereport_active)
9805                         R_TimeReport("particles");
9806
9807                 R_DrawExplosions();
9808                 if (r_timereport_active)
9809                         R_TimeReport("explosions");
9810
9811                 R_DrawLightningBeams();
9812                 if (r_timereport_active)
9813                         R_TimeReport("lightning");
9814         }
9815
9816         VM_CL_AddPolygonsToMeshQueue();
9817
9818         if (r_refdef.view.showdebug)
9819         {
9820                 if (cl_locs_show.integer)
9821                 {
9822                         R_DrawLocs();
9823                         if (r_timereport_active)
9824                                 R_TimeReport("showlocs");
9825                 }
9826
9827                 if (r_drawportals.integer)
9828                 {
9829                         R_DrawPortals();
9830                         if (r_timereport_active)
9831                                 R_TimeReport("portals");
9832                 }
9833
9834                 if (r_showbboxes.value > 0)
9835                 {
9836                         R_DrawEntityBBoxes();
9837                         if (r_timereport_active)
9838                                 R_TimeReport("bboxes");
9839                 }
9840         }
9841
9842         R_MeshQueue_RenderTransparent();
9843         if (r_timereport_active)
9844                 R_TimeReport("drawtrans");
9845
9846         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))
9847         {
9848                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9849                 if (r_timereport_active)
9850                         R_TimeReport("worlddebug");
9851                 R_DrawModelsDebug();
9852                 if (r_timereport_active)
9853                         R_TimeReport("modeldebug");
9854         }
9855
9856         if (cl.csqc_vidvars.drawworld)
9857         {
9858                 R_Shadow_DrawCoronas();
9859                 if (r_timereport_active)
9860                         R_TimeReport("coronas");
9861         }
9862
9863         // don't let sound skip if going slow
9864         if (r_refdef.scene.extraupdate)
9865                 S_ExtraUpdate ();
9866
9867         R_ResetViewRendering2D();
9868 }
9869
9870 static const unsigned short bboxelements[36] =
9871 {
9872         5, 1, 3, 5, 3, 7,
9873         6, 2, 0, 6, 0, 4,
9874         7, 3, 2, 7, 2, 6,
9875         4, 0, 1, 4, 1, 5,
9876         4, 5, 7, 4, 7, 6,
9877         1, 0, 2, 1, 2, 3,
9878 };
9879
9880 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9881 {
9882         int i;
9883         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9884
9885         RSurf_ActiveWorldEntity();
9886
9887         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9888         GL_DepthMask(false);
9889         GL_DepthRange(0, 1);
9890         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9891         R_Mesh_ResetTextureState();
9892
9893         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9894         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9895         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9896         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9897         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9898         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9899         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9900         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9901         R_FillColors(color4f, 8, cr, cg, cb, ca);
9902         if (r_refdef.fogenabled)
9903         {
9904                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9905                 {
9906                         f1 = RSurf_FogVertex(v);
9907                         f2 = 1 - f1;
9908                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9909                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9910                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9911                 }
9912         }
9913         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9914         R_Mesh_ResetTextureState();
9915         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9916         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9917 }
9918
9919 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9920 {
9921         int i;
9922         float color[4];
9923         prvm_edict_t *edict;
9924         prvm_prog_t *prog_save = prog;
9925
9926         // this function draws bounding boxes of server entities
9927         if (!sv.active)
9928                 return;
9929
9930         GL_CullFace(GL_NONE);
9931         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9932
9933         prog = 0;
9934         SV_VM_Begin();
9935         for (i = 0;i < numsurfaces;i++)
9936         {
9937                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9938                 switch ((int)edict->fields.server->solid)
9939                 {
9940                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9941                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9942                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9943                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9944                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9945                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9946                 }
9947                 color[3] *= r_showbboxes.value;
9948                 color[3] = bound(0, color[3], 1);
9949                 GL_DepthTest(!r_showdisabledepthtest.integer);
9950                 GL_CullFace(r_refdef.view.cullface_front);
9951                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9952         }
9953         SV_VM_End();
9954         prog = prog_save;
9955 }
9956
9957 static void R_DrawEntityBBoxes(void)
9958 {
9959         int i;
9960         prvm_edict_t *edict;
9961         vec3_t center;
9962         prvm_prog_t *prog_save = prog;
9963
9964         // this function draws bounding boxes of server entities
9965         if (!sv.active)
9966                 return;
9967
9968         prog = 0;
9969         SV_VM_Begin();
9970         for (i = 0;i < prog->num_edicts;i++)
9971         {
9972                 edict = PRVM_EDICT_NUM(i);
9973                 if (edict->priv.server->free)
9974                         continue;
9975                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9976                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9977                         continue;
9978                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9979                         continue;
9980                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9981                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9982         }
9983         SV_VM_End();
9984         prog = prog_save;
9985 }
9986
9987 static const int nomodelelement3i[24] =
9988 {
9989         5, 2, 0,
9990         5, 1, 2,
9991         5, 0, 3,
9992         5, 3, 1,
9993         0, 2, 4,
9994         2, 1, 4,
9995         3, 0, 4,
9996         1, 3, 4
9997 };
9998
9999 static const unsigned short nomodelelement3s[24] =
10000 {
10001         5, 2, 0,
10002         5, 1, 2,
10003         5, 0, 3,
10004         5, 3, 1,
10005         0, 2, 4,
10006         2, 1, 4,
10007         3, 0, 4,
10008         1, 3, 4
10009 };
10010
10011 static const float nomodelvertex3f[6*3] =
10012 {
10013         -16,   0,   0,
10014          16,   0,   0,
10015           0, -16,   0,
10016           0,  16,   0,
10017           0,   0, -16,
10018           0,   0,  16
10019 };
10020
10021 static const float nomodelcolor4f[6*4] =
10022 {
10023         0.0f, 0.0f, 0.5f, 1.0f,
10024         0.0f, 0.0f, 0.5f, 1.0f,
10025         0.0f, 0.5f, 0.0f, 1.0f,
10026         0.0f, 0.5f, 0.0f, 1.0f,
10027         0.5f, 0.0f, 0.0f, 1.0f,
10028         0.5f, 0.0f, 0.0f, 1.0f
10029 };
10030
10031 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10032 {
10033         int i;
10034         float f1, f2, *c;
10035         float color4f[6*4];
10036
10037         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);
10038
10039         // this is only called once per entity so numsurfaces is always 1, and
10040         // surfacelist is always {0}, so this code does not handle batches
10041
10042         if (rsurface.ent_flags & RENDER_ADDITIVE)
10043         {
10044                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10045                 GL_DepthMask(false);
10046         }
10047         else if (rsurface.colormod[3] < 1)
10048         {
10049                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10050                 GL_DepthMask(false);
10051         }
10052         else
10053         {
10054                 GL_BlendFunc(GL_ONE, GL_ZERO);
10055                 GL_DepthMask(true);
10056         }
10057         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10058         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10059         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10060         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10061         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10062         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10063         for (i = 0, c = color4f;i < 6;i++, c += 4)
10064         {
10065                 c[0] *= rsurface.colormod[0];
10066                 c[1] *= rsurface.colormod[1];
10067                 c[2] *= rsurface.colormod[2];
10068                 c[3] *= rsurface.colormod[3];
10069         }
10070         if (r_refdef.fogenabled)
10071         {
10072                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10073                 {
10074                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10075                         f2 = 1 - f1;
10076                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10077                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10078                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10079                 }
10080         }
10081         R_Mesh_ResetTextureState();
10082         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10083         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10084 }
10085
10086 void R_DrawNoModel(entity_render_t *ent)
10087 {
10088         vec3_t org;
10089         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10090         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10091                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10092         else
10093                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10094 }
10095
10096 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10097 {
10098         vec3_t right1, right2, diff, normal;
10099
10100         VectorSubtract (org2, org1, normal);
10101
10102         // calculate 'right' vector for start
10103         VectorSubtract (r_refdef.view.origin, org1, diff);
10104         CrossProduct (normal, diff, right1);
10105         VectorNormalize (right1);
10106
10107         // calculate 'right' vector for end
10108         VectorSubtract (r_refdef.view.origin, org2, diff);
10109         CrossProduct (normal, diff, right2);
10110         VectorNormalize (right2);
10111
10112         vert[ 0] = org1[0] + width * right1[0];
10113         vert[ 1] = org1[1] + width * right1[1];
10114         vert[ 2] = org1[2] + width * right1[2];
10115         vert[ 3] = org1[0] - width * right1[0];
10116         vert[ 4] = org1[1] - width * right1[1];
10117         vert[ 5] = org1[2] - width * right1[2];
10118         vert[ 6] = org2[0] - width * right2[0];
10119         vert[ 7] = org2[1] - width * right2[1];
10120         vert[ 8] = org2[2] - width * right2[2];
10121         vert[ 9] = org2[0] + width * right2[0];
10122         vert[10] = org2[1] + width * right2[1];
10123         vert[11] = org2[2] + width * right2[2];
10124 }
10125
10126 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)
10127 {
10128         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10129         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10130         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10131         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10132         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10133         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10134         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10135         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10136         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10137         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10138         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10139         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10140 }
10141
10142 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10143 {
10144         int i;
10145         float *vertex3f;
10146         float v[3];
10147         VectorSet(v, x, y, z);
10148         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10149                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10150                         break;
10151         if (i == mesh->numvertices)
10152         {
10153                 if (mesh->numvertices < mesh->maxvertices)
10154                 {
10155                         VectorCopy(v, vertex3f);
10156                         mesh->numvertices++;
10157                 }
10158                 return mesh->numvertices;
10159         }
10160         else
10161                 return i;
10162 }
10163
10164 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10165 {
10166         int i;
10167         int *e, element[3];
10168         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10169         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10170         e = mesh->element3i + mesh->numtriangles * 3;
10171         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10172         {
10173                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10174                 if (mesh->numtriangles < mesh->maxtriangles)
10175                 {
10176                         *e++ = element[0];
10177                         *e++ = element[1];
10178                         *e++ = element[2];
10179                         mesh->numtriangles++;
10180                 }
10181                 element[1] = element[2];
10182         }
10183 }
10184
10185 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10186 {
10187         int i;
10188         int *e, element[3];
10189         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10190         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10191         e = mesh->element3i + mesh->numtriangles * 3;
10192         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10193         {
10194                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10195                 if (mesh->numtriangles < mesh->maxtriangles)
10196                 {
10197                         *e++ = element[0];
10198                         *e++ = element[1];
10199                         *e++ = element[2];
10200                         mesh->numtriangles++;
10201                 }
10202                 element[1] = element[2];
10203         }
10204 }
10205
10206 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10207 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10208 {
10209         int planenum, planenum2;
10210         int w;
10211         int tempnumpoints;
10212         mplane_t *plane, *plane2;
10213         double maxdist;
10214         double temppoints[2][256*3];
10215         // figure out how large a bounding box we need to properly compute this brush
10216         maxdist = 0;
10217         for (w = 0;w < numplanes;w++)
10218                 maxdist = max(maxdist, fabs(planes[w].dist));
10219         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10220         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10221         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10222         {
10223                 w = 0;
10224                 tempnumpoints = 4;
10225                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10226                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10227                 {
10228                         if (planenum2 == planenum)
10229                                 continue;
10230                         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);
10231                         w = !w;
10232                 }
10233                 if (tempnumpoints < 3)
10234                         continue;
10235                 // generate elements forming a triangle fan for this polygon
10236                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10237         }
10238 }
10239
10240 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)
10241 {
10242         texturelayer_t *layer;
10243         layer = t->currentlayers + t->currentnumlayers++;
10244         layer->type = type;
10245         layer->depthmask = depthmask;
10246         layer->blendfunc1 = blendfunc1;
10247         layer->blendfunc2 = blendfunc2;
10248         layer->texture = texture;
10249         layer->texmatrix = *matrix;
10250         layer->color[0] = r;
10251         layer->color[1] = g;
10252         layer->color[2] = b;
10253         layer->color[3] = a;
10254 }
10255
10256 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10257 {
10258         if(parms[0] == 0 && parms[1] == 0)
10259                 return false;
10260         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10261                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10262                         return false;
10263         return true;
10264 }
10265
10266 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10267 {
10268         double index, f;
10269         index = parms[2] + r_refdef.scene.time * parms[3];
10270         index -= floor(index);
10271         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10272         {
10273         default:
10274         case Q3WAVEFUNC_NONE:
10275         case Q3WAVEFUNC_NOISE:
10276         case Q3WAVEFUNC_COUNT:
10277                 f = 0;
10278                 break;
10279         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10280         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10281         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10282         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10283         case Q3WAVEFUNC_TRIANGLE:
10284                 index *= 4;
10285                 f = index - floor(index);
10286                 if (index < 1)
10287                         f = f;
10288                 else if (index < 2)
10289                         f = 1 - f;
10290                 else if (index < 3)
10291                         f = -f;
10292                 else
10293                         f = -(1 - f);
10294                 break;
10295         }
10296         f = parms[0] + parms[1] * f;
10297         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10298                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10299         return (float) f;
10300 }
10301
10302 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10303 {
10304         int w, h, idx;
10305         float f;
10306         float tcmat[12];
10307         matrix4x4_t matrix, temp;
10308         switch(tcmod->tcmod)
10309         {
10310                 case Q3TCMOD_COUNT:
10311                 case Q3TCMOD_NONE:
10312                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10313                                 matrix = r_waterscrollmatrix;
10314                         else
10315                                 matrix = identitymatrix;
10316                         break;
10317                 case Q3TCMOD_ENTITYTRANSLATE:
10318                         // this is used in Q3 to allow the gamecode to control texcoord
10319                         // scrolling on the entity, which is not supported in darkplaces yet.
10320                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10321                         break;
10322                 case Q3TCMOD_ROTATE:
10323                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10324                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10325                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10326                         break;
10327                 case Q3TCMOD_SCALE:
10328                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10329                         break;
10330                 case Q3TCMOD_SCROLL:
10331                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10332                         break;
10333                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10334                         w = (int) tcmod->parms[0];
10335                         h = (int) tcmod->parms[1];
10336                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10337                         f = f - floor(f);
10338                         idx = (int) floor(f * w * h);
10339                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10340                         break;
10341                 case Q3TCMOD_STRETCH:
10342                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10343                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10344                         break;
10345                 case Q3TCMOD_TRANSFORM:
10346                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10347                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10348                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10349                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10350                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10351                         break;
10352                 case Q3TCMOD_TURBULENT:
10353                         // this is handled in the RSurf_PrepareVertices function
10354                         matrix = identitymatrix;
10355                         break;
10356         }
10357         temp = *texmatrix;
10358         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10359 }
10360
10361 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10362 {
10363         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10364         char name[MAX_QPATH];
10365         skinframe_t *skinframe;
10366         unsigned char pixels[296*194];
10367         strlcpy(cache->name, skinname, sizeof(cache->name));
10368         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10369         if (developer_loading.integer)
10370                 Con_Printf("loading %s\n", name);
10371         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10372         if (!skinframe || !skinframe->base)
10373         {
10374                 unsigned char *f;
10375                 fs_offset_t filesize;
10376                 skinframe = NULL;
10377                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10378                 if (f)
10379                 {
10380                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10381                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10382                         Mem_Free(f);
10383                 }
10384         }
10385         cache->skinframe = skinframe;
10386 }
10387
10388 texture_t *R_GetCurrentTexture(texture_t *t)
10389 {
10390         int i;
10391         const entity_render_t *ent = rsurface.entity;
10392         dp_model_t *model = ent->model;
10393         q3shaderinfo_layer_tcmod_t *tcmod;
10394
10395         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10396                 return t->currentframe;
10397         t->update_lastrenderframe = r_textureframe;
10398         t->update_lastrenderentity = (void *)ent;
10399
10400         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10401                 t->camera_entity = ent->entitynumber;
10402         else
10403                 t->camera_entity = 0;
10404
10405         // switch to an alternate material if this is a q1bsp animated material
10406         {
10407                 texture_t *texture = t;
10408                 int s = rsurface.ent_skinnum;
10409                 if ((unsigned int)s >= (unsigned int)model->numskins)
10410                         s = 0;
10411                 if (model->skinscenes)
10412                 {
10413                         if (model->skinscenes[s].framecount > 1)
10414                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10415                         else
10416                                 s = model->skinscenes[s].firstframe;
10417                 }
10418                 if (s > 0)
10419                         t = t + s * model->num_surfaces;
10420                 if (t->animated)
10421                 {
10422                         // use an alternate animation if the entity's frame is not 0,
10423                         // and only if the texture has an alternate animation
10424                         if (rsurface.ent_alttextures && t->anim_total[1])
10425                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10426                         else
10427                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10428                 }
10429                 texture->currentframe = t;
10430         }
10431
10432         // update currentskinframe to be a qw skin or animation frame
10433         if (rsurface.ent_qwskin >= 0)
10434         {
10435                 i = rsurface.ent_qwskin;
10436                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10437                 {
10438                         r_qwskincache_size = cl.maxclients;
10439                         if (r_qwskincache)
10440                                 Mem_Free(r_qwskincache);
10441                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10442                 }
10443                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10444                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10445                 t->currentskinframe = r_qwskincache[i].skinframe;
10446                 if (t->currentskinframe == NULL)
10447                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10448         }
10449         else if (t->numskinframes >= 2)
10450                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10451         if (t->backgroundnumskinframes >= 2)
10452                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10453
10454         t->currentmaterialflags = t->basematerialflags;
10455         t->currentalpha = rsurface.colormod[3];
10456         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10457                 t->currentalpha *= r_wateralpha.value;
10458         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10459                 t->currentalpha *= t->r_water_wateralpha;
10460         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10461                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10462         if (!(rsurface.ent_flags & RENDER_LIGHT))
10463                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10464         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10465         {
10466                 // pick a model lighting mode
10467                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10468                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10469                 else
10470                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10471         }
10472         if (rsurface.ent_flags & RENDER_ADDITIVE)
10473                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10474         else if (t->currentalpha < 1)
10475                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10476         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10477                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10478         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10479                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10480         if (t->backgroundnumskinframes)
10481                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10482         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10483         {
10484                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10485                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10486         }
10487         else
10488                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10489         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10490                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10491
10492         // there is no tcmod
10493         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10494         {
10495                 t->currenttexmatrix = r_waterscrollmatrix;
10496                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10497         }
10498         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10499         {
10500                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10501                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10502         }
10503
10504         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10505                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10506         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10507                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10508
10509         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10510         if (t->currentskinframe->qpixels)
10511                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10512         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10513         if (!t->basetexture)
10514                 t->basetexture = r_texture_notexture;
10515         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10516         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10517         t->nmaptexture = t->currentskinframe->nmap;
10518         if (!t->nmaptexture)
10519                 t->nmaptexture = r_texture_blanknormalmap;
10520         t->glosstexture = r_texture_black;
10521         t->glowtexture = t->currentskinframe->glow;
10522         t->fogtexture = t->currentskinframe->fog;
10523         t->reflectmasktexture = t->currentskinframe->reflect;
10524         if (t->backgroundnumskinframes)
10525         {
10526                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10527                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10528                 t->backgroundglosstexture = r_texture_black;
10529                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10530                 if (!t->backgroundnmaptexture)
10531                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10532         }
10533         else
10534         {
10535                 t->backgroundbasetexture = r_texture_white;
10536                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10537                 t->backgroundglosstexture = r_texture_black;
10538                 t->backgroundglowtexture = NULL;
10539         }
10540         t->specularpower = r_shadow_glossexponent.value;
10541         // TODO: store reference values for these in the texture?
10542         t->specularscale = 0;
10543         if (r_shadow_gloss.integer > 0)
10544         {
10545                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10546                 {
10547                         if (r_shadow_glossintensity.value > 0)
10548                         {
10549                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10550                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10551                                 t->specularscale = r_shadow_glossintensity.value;
10552                         }
10553                 }
10554                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10555                 {
10556                         t->glosstexture = r_texture_white;
10557                         t->backgroundglosstexture = r_texture_white;
10558                         t->specularscale = r_shadow_gloss2intensity.value;
10559                         t->specularpower = r_shadow_gloss2exponent.value;
10560                 }
10561         }
10562         t->specularscale *= t->specularscalemod;
10563         t->specularpower *= t->specularpowermod;
10564
10565         // lightmaps mode looks bad with dlights using actual texturing, so turn
10566         // off the colormap and glossmap, but leave the normalmap on as it still
10567         // accurately represents the shading involved
10568         if (gl_lightmaps.integer)
10569         {
10570                 t->basetexture = r_texture_grey128;
10571                 t->pantstexture = r_texture_black;
10572                 t->shirttexture = r_texture_black;
10573                 t->nmaptexture = r_texture_blanknormalmap;
10574                 t->glosstexture = r_texture_black;
10575                 t->glowtexture = NULL;
10576                 t->fogtexture = NULL;
10577                 t->reflectmasktexture = NULL;
10578                 t->backgroundbasetexture = NULL;
10579                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10580                 t->backgroundglosstexture = r_texture_black;
10581                 t->backgroundglowtexture = NULL;
10582                 t->specularscale = 0;
10583                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10584         }
10585
10586         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10587         VectorClear(t->dlightcolor);
10588         t->currentnumlayers = 0;
10589         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10590         {
10591                 int blendfunc1, blendfunc2;
10592                 qboolean depthmask;
10593                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10594                 {
10595                         blendfunc1 = GL_SRC_ALPHA;
10596                         blendfunc2 = GL_ONE;
10597                 }
10598                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10599                 {
10600                         blendfunc1 = GL_SRC_ALPHA;
10601                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10602                 }
10603                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10604                 {
10605                         blendfunc1 = t->customblendfunc[0];
10606                         blendfunc2 = t->customblendfunc[1];
10607                 }
10608                 else
10609                 {
10610                         blendfunc1 = GL_ONE;
10611                         blendfunc2 = GL_ZERO;
10612                 }
10613                 // don't colormod evilblend textures
10614                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10615                         VectorSet(t->lightmapcolor, 1, 1, 1);
10616                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10617                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10618                 {
10619                         // fullbright is not affected by r_refdef.lightmapintensity
10620                         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]);
10621                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10622                                 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]);
10623                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10624                                 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]);
10625                 }
10626                 else
10627                 {
10628                         vec3_t ambientcolor;
10629                         float colorscale;
10630                         // set the color tint used for lights affecting this surface
10631                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10632                         colorscale = 2;
10633                         // q3bsp has no lightmap updates, so the lightstylevalue that
10634                         // would normally be baked into the lightmap must be
10635                         // applied to the color
10636                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10637                         if (model->type == mod_brushq3)
10638                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10639                         colorscale *= r_refdef.lightmapintensity;
10640                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10641                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10642                         // basic lit geometry
10643                         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]);
10644                         // add pants/shirt if needed
10645                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10646                                 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]);
10647                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10648                                 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]);
10649                         // now add ambient passes if needed
10650                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10651                         {
10652                                 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]);
10653                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10654                                         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]);
10655                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10656                                         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]);
10657                         }
10658                 }
10659                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10660                         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]);
10661                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10662                 {
10663                         // if this is opaque use alpha blend which will darken the earlier
10664                         // passes cheaply.
10665                         //
10666                         // if this is an alpha blended material, all the earlier passes
10667                         // were darkened by fog already, so we only need to add the fog
10668                         // color ontop through the fog mask texture
10669                         //
10670                         // if this is an additive blended material, all the earlier passes
10671                         // were darkened by fog already, and we should not add fog color
10672                         // (because the background was not darkened, there is no fog color
10673                         // that was lost behind it).
10674                         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]);
10675                 }
10676         }
10677
10678         return t->currentframe;
10679 }
10680
10681 rsurfacestate_t rsurface;
10682
10683 void R_Mesh_ResizeArrays(int newvertices)
10684 {
10685         unsigned char *base;
10686         size_t size;
10687         if (rsurface.array_size >= newvertices)
10688                 return;
10689         if (rsurface.array_base)
10690                 Mem_Free(rsurface.array_base);
10691         rsurface.array_size = (newvertices + 1023) & ~1023;
10692         size = 0;
10693         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10694         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10695         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10696         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10697         size += rsurface.array_size * sizeof(float[3]);
10698         size += rsurface.array_size * sizeof(float[3]);
10699         size += rsurface.array_size * sizeof(float[3]);
10700         size += rsurface.array_size * sizeof(float[3]);
10701         size += rsurface.array_size * sizeof(float[3]);
10702         size += rsurface.array_size * sizeof(float[3]);
10703         size += rsurface.array_size * sizeof(float[3]);
10704         size += rsurface.array_size * sizeof(float[3]);
10705         size += rsurface.array_size * sizeof(float[4]);
10706         size += rsurface.array_size * sizeof(float[2]);
10707         size += rsurface.array_size * sizeof(float[2]);
10708         size += rsurface.array_size * sizeof(float[4]);
10709         size += rsurface.array_size * sizeof(int[3]);
10710         size += rsurface.array_size * sizeof(unsigned short[3]);
10711         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10712         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10713         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10714         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10715         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10716         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10717         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10718         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10719         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10720         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10721         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10722         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10723         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10724         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10725         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10726         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10727         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10728         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10729         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10730 }
10731
10732 void RSurf_ActiveWorldEntity(void)
10733 {
10734         dp_model_t *model = r_refdef.scene.worldmodel;
10735         //if (rsurface.entity == r_refdef.scene.worldentity)
10736         //      return;
10737         rsurface.entity = r_refdef.scene.worldentity;
10738         rsurface.skeleton = NULL;
10739         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10740         rsurface.ent_skinnum = 0;
10741         rsurface.ent_qwskin = -1;
10742         rsurface.ent_shadertime = 0;
10743         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10744         if (rsurface.array_size < model->surfmesh.num_vertices)
10745                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10746         rsurface.matrix = identitymatrix;
10747         rsurface.inversematrix = identitymatrix;
10748         rsurface.matrixscale = 1;
10749         rsurface.inversematrixscale = 1;
10750         R_EntityMatrix(&identitymatrix);
10751         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10752         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10753         rsurface.fograngerecip = r_refdef.fograngerecip;
10754         rsurface.fogheightfade = r_refdef.fogheightfade;
10755         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10756         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10757         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10758         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10759         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10760         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10761         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10762         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10763         rsurface.colormod[3] = 1;
10764         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);
10765         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10766         rsurface.frameblend[0].lerp = 1;
10767         rsurface.ent_alttextures = false;
10768         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10769         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10770         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10771         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10772         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10773         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10774         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10775         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10776         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10777         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10778         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10779         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10780         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10781         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10782         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10783         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10784         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10785         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10786         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10787         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10788         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10789         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10790         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10791         rsurface.modelelement3i = model->surfmesh.data_element3i;
10792         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10793         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10794         rsurface.modelelement3s = model->surfmesh.data_element3s;
10795         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10796         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10797         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10798         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10799         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10800         rsurface.modelsurfaces = model->data_surfaces;
10801         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10802         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10803         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10804         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10805         rsurface.modelgeneratedvertex = false;
10806         rsurface.batchgeneratedvertex = false;
10807         rsurface.batchfirstvertex = 0;
10808         rsurface.batchnumvertices = 0;
10809         rsurface.batchfirsttriangle = 0;
10810         rsurface.batchnumtriangles = 0;
10811         rsurface.batchvertex3f  = NULL;
10812         rsurface.batchvertex3f_vertexbuffer = NULL;
10813         rsurface.batchvertex3f_bufferoffset = 0;
10814         rsurface.batchsvector3f = NULL;
10815         rsurface.batchsvector3f_vertexbuffer = NULL;
10816         rsurface.batchsvector3f_bufferoffset = 0;
10817         rsurface.batchtvector3f = NULL;
10818         rsurface.batchtvector3f_vertexbuffer = NULL;
10819         rsurface.batchtvector3f_bufferoffset = 0;
10820         rsurface.batchnormal3f  = NULL;
10821         rsurface.batchnormal3f_vertexbuffer = NULL;
10822         rsurface.batchnormal3f_bufferoffset = 0;
10823         rsurface.batchlightmapcolor4f = NULL;
10824         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10825         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10826         rsurface.batchtexcoordtexture2f = NULL;
10827         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10828         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10829         rsurface.batchtexcoordlightmap2f = NULL;
10830         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10831         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10832         rsurface.batchvertexmesh = NULL;
10833         rsurface.batchvertexmeshbuffer = NULL;
10834         rsurface.batchvertexposition = NULL;
10835         rsurface.batchvertexpositionbuffer = NULL;
10836         rsurface.batchelement3i = NULL;
10837         rsurface.batchelement3i_indexbuffer = NULL;
10838         rsurface.batchelement3i_bufferoffset = 0;
10839         rsurface.batchelement3s = NULL;
10840         rsurface.batchelement3s_indexbuffer = NULL;
10841         rsurface.batchelement3s_bufferoffset = 0;
10842         rsurface.passcolor4f = NULL;
10843         rsurface.passcolor4f_vertexbuffer = NULL;
10844         rsurface.passcolor4f_bufferoffset = 0;
10845 }
10846
10847 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10848 {
10849         dp_model_t *model = ent->model;
10850         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10851         //      return;
10852         rsurface.entity = (entity_render_t *)ent;
10853         rsurface.skeleton = ent->skeleton;
10854         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10855         rsurface.ent_skinnum = ent->skinnum;
10856         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;
10857         rsurface.ent_shadertime = ent->shadertime;
10858         rsurface.ent_flags = ent->flags;
10859         if (rsurface.array_size < model->surfmesh.num_vertices)
10860                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10861         rsurface.matrix = ent->matrix;
10862         rsurface.inversematrix = ent->inversematrix;
10863         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10864         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10865         R_EntityMatrix(&rsurface.matrix);
10866         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10867         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10868         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10869         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10870         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10871         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10872         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10873         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10874         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10875         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10876         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10877         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10878         rsurface.colormod[3] = ent->alpha;
10879         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10880         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10881         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10882         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10883         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10884         if (ent->model->brush.submodel && !prepass)
10885         {
10886                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10887                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10888         }
10889         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10890         {
10891                 if (ent->animcache_vertex3f && !r_framedata_failed)
10892                 {
10893                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10894                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10895                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10896                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10897                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10898                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10899                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10900                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10901                 }
10902                 else if (wanttangents)
10903                 {
10904                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10905                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10906                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10907                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10908                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10909                         rsurface.modelvertexmesh = NULL;
10910                         rsurface.modelvertexmeshbuffer = NULL;
10911                         rsurface.modelvertexposition = NULL;
10912                         rsurface.modelvertexpositionbuffer = NULL;
10913                 }
10914                 else if (wantnormals)
10915                 {
10916                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10917                         rsurface.modelsvector3f = NULL;
10918                         rsurface.modeltvector3f = NULL;
10919                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10920                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10921                         rsurface.modelvertexmesh = NULL;
10922                         rsurface.modelvertexmeshbuffer = NULL;
10923                         rsurface.modelvertexposition = NULL;
10924                         rsurface.modelvertexpositionbuffer = NULL;
10925                 }
10926                 else
10927                 {
10928                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10929                         rsurface.modelsvector3f = NULL;
10930                         rsurface.modeltvector3f = NULL;
10931                         rsurface.modelnormal3f = NULL;
10932                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10933                         rsurface.modelvertexmesh = NULL;
10934                         rsurface.modelvertexmeshbuffer = NULL;
10935                         rsurface.modelvertexposition = NULL;
10936                         rsurface.modelvertexpositionbuffer = NULL;
10937                 }
10938                 rsurface.modelvertex3f_vertexbuffer = 0;
10939                 rsurface.modelvertex3f_bufferoffset = 0;
10940                 rsurface.modelsvector3f_vertexbuffer = 0;
10941                 rsurface.modelsvector3f_bufferoffset = 0;
10942                 rsurface.modeltvector3f_vertexbuffer = 0;
10943                 rsurface.modeltvector3f_bufferoffset = 0;
10944                 rsurface.modelnormal3f_vertexbuffer = 0;
10945                 rsurface.modelnormal3f_bufferoffset = 0;
10946                 rsurface.modelgeneratedvertex = true;
10947         }
10948         else
10949         {
10950                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10951                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10952                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10953                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10954                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10955                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10956                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10957                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10958                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10959                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10960                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10961                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10962                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10963                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10964                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10965                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10966                 rsurface.modelgeneratedvertex = false;
10967         }
10968         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10969         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10970         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10971         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10972         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10973         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10974         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10975         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10976         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10977         rsurface.modelelement3i = model->surfmesh.data_element3i;
10978         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10979         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10980         rsurface.modelelement3s = model->surfmesh.data_element3s;
10981         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10982         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10983         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10984         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10985         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10986         rsurface.modelsurfaces = model->data_surfaces;
10987         rsurface.batchgeneratedvertex = false;
10988         rsurface.batchfirstvertex = 0;
10989         rsurface.batchnumvertices = 0;
10990         rsurface.batchfirsttriangle = 0;
10991         rsurface.batchnumtriangles = 0;
10992         rsurface.batchvertex3f  = NULL;
10993         rsurface.batchvertex3f_vertexbuffer = NULL;
10994         rsurface.batchvertex3f_bufferoffset = 0;
10995         rsurface.batchsvector3f = NULL;
10996         rsurface.batchsvector3f_vertexbuffer = NULL;
10997         rsurface.batchsvector3f_bufferoffset = 0;
10998         rsurface.batchtvector3f = NULL;
10999         rsurface.batchtvector3f_vertexbuffer = NULL;
11000         rsurface.batchtvector3f_bufferoffset = 0;
11001         rsurface.batchnormal3f  = NULL;
11002         rsurface.batchnormal3f_vertexbuffer = NULL;
11003         rsurface.batchnormal3f_bufferoffset = 0;
11004         rsurface.batchlightmapcolor4f = NULL;
11005         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11006         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11007         rsurface.batchtexcoordtexture2f = NULL;
11008         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11009         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11010         rsurface.batchtexcoordlightmap2f = NULL;
11011         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11012         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11013         rsurface.batchvertexmesh = NULL;
11014         rsurface.batchvertexmeshbuffer = NULL;
11015         rsurface.batchvertexposition = NULL;
11016         rsurface.batchvertexpositionbuffer = NULL;
11017         rsurface.batchelement3i = NULL;
11018         rsurface.batchelement3i_indexbuffer = NULL;
11019         rsurface.batchelement3i_bufferoffset = 0;
11020         rsurface.batchelement3s = NULL;
11021         rsurface.batchelement3s_indexbuffer = NULL;
11022         rsurface.batchelement3s_bufferoffset = 0;
11023         rsurface.passcolor4f = NULL;
11024         rsurface.passcolor4f_vertexbuffer = NULL;
11025         rsurface.passcolor4f_bufferoffset = 0;
11026 }
11027
11028 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)
11029 {
11030         int i;
11031
11032         rsurface.entity = r_refdef.scene.worldentity;
11033         rsurface.skeleton = NULL;
11034         rsurface.ent_skinnum = 0;
11035         rsurface.ent_qwskin = -1;
11036         rsurface.ent_shadertime = shadertime;
11037         rsurface.ent_flags = entflags;
11038         rsurface.modelnumvertices = numvertices;
11039         rsurface.modelnumtriangles = numtriangles;
11040         if (rsurface.array_size < rsurface.modelnumvertices)
11041                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11042         rsurface.matrix = *matrix;
11043         rsurface.inversematrix = *inversematrix;
11044         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11045         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11046         R_EntityMatrix(&rsurface.matrix);
11047         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11048         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11049         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11050         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11051         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11052         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11053         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11054         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11055         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11056         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11057         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11058         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11059         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);
11060         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11061         rsurface.frameblend[0].lerp = 1;
11062         rsurface.ent_alttextures = false;
11063         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11064         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11065         if (wanttangents)
11066         {
11067                 rsurface.modelvertex3f = vertex3f;
11068                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11069                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11070                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11071         }
11072         else if (wantnormals)
11073         {
11074                 rsurface.modelvertex3f = vertex3f;
11075                 rsurface.modelsvector3f = NULL;
11076                 rsurface.modeltvector3f = NULL;
11077                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11078         }
11079         else
11080         {
11081                 rsurface.modelvertex3f = vertex3f;
11082                 rsurface.modelsvector3f = NULL;
11083                 rsurface.modeltvector3f = NULL;
11084                 rsurface.modelnormal3f = NULL;
11085         }
11086         rsurface.modelvertexmesh = NULL;
11087         rsurface.modelvertexmeshbuffer = NULL;
11088         rsurface.modelvertexposition = NULL;
11089         rsurface.modelvertexpositionbuffer = NULL;
11090         rsurface.modelvertex3f_vertexbuffer = 0;
11091         rsurface.modelvertex3f_bufferoffset = 0;
11092         rsurface.modelsvector3f_vertexbuffer = 0;
11093         rsurface.modelsvector3f_bufferoffset = 0;
11094         rsurface.modeltvector3f_vertexbuffer = 0;
11095         rsurface.modeltvector3f_bufferoffset = 0;
11096         rsurface.modelnormal3f_vertexbuffer = 0;
11097         rsurface.modelnormal3f_bufferoffset = 0;
11098         rsurface.modelgeneratedvertex = true;
11099         rsurface.modellightmapcolor4f  = color4f;
11100         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11101         rsurface.modellightmapcolor4f_bufferoffset = 0;
11102         rsurface.modeltexcoordtexture2f  = texcoord2f;
11103         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11104         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11105         rsurface.modeltexcoordlightmap2f  = NULL;
11106         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11107         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11108         rsurface.modelelement3i = element3i;
11109         rsurface.modelelement3i_indexbuffer = NULL;
11110         rsurface.modelelement3i_bufferoffset = 0;
11111         rsurface.modelelement3s = element3s;
11112         rsurface.modelelement3s_indexbuffer = NULL;
11113         rsurface.modelelement3s_bufferoffset = 0;
11114         rsurface.modellightmapoffsets = NULL;
11115         rsurface.modelsurfaces = NULL;
11116         rsurface.batchgeneratedvertex = false;
11117         rsurface.batchfirstvertex = 0;
11118         rsurface.batchnumvertices = 0;
11119         rsurface.batchfirsttriangle = 0;
11120         rsurface.batchnumtriangles = 0;
11121         rsurface.batchvertex3f  = NULL;
11122         rsurface.batchvertex3f_vertexbuffer = NULL;
11123         rsurface.batchvertex3f_bufferoffset = 0;
11124         rsurface.batchsvector3f = NULL;
11125         rsurface.batchsvector3f_vertexbuffer = NULL;
11126         rsurface.batchsvector3f_bufferoffset = 0;
11127         rsurface.batchtvector3f = NULL;
11128         rsurface.batchtvector3f_vertexbuffer = NULL;
11129         rsurface.batchtvector3f_bufferoffset = 0;
11130         rsurface.batchnormal3f  = NULL;
11131         rsurface.batchnormal3f_vertexbuffer = NULL;
11132         rsurface.batchnormal3f_bufferoffset = 0;
11133         rsurface.batchlightmapcolor4f = NULL;
11134         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11135         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11136         rsurface.batchtexcoordtexture2f = NULL;
11137         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11138         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11139         rsurface.batchtexcoordlightmap2f = NULL;
11140         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11141         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11142         rsurface.batchvertexmesh = NULL;
11143         rsurface.batchvertexmeshbuffer = NULL;
11144         rsurface.batchvertexposition = NULL;
11145         rsurface.batchvertexpositionbuffer = NULL;
11146         rsurface.batchelement3i = NULL;
11147         rsurface.batchelement3i_indexbuffer = NULL;
11148         rsurface.batchelement3i_bufferoffset = 0;
11149         rsurface.batchelement3s = NULL;
11150         rsurface.batchelement3s_indexbuffer = NULL;
11151         rsurface.batchelement3s_bufferoffset = 0;
11152         rsurface.passcolor4f = NULL;
11153         rsurface.passcolor4f_vertexbuffer = NULL;
11154         rsurface.passcolor4f_bufferoffset = 0;
11155
11156         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11157         {
11158                 if ((wantnormals || wanttangents) && !normal3f)
11159                 {
11160                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11161                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11162                 }
11163                 if (wanttangents && !svector3f)
11164                 {
11165                         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);
11166                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11167                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11168                 }
11169         }
11170
11171         // now convert arrays into vertexmesh structs
11172         for (i = 0;i < numvertices;i++)
11173         {
11174                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11175                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11176                 if (rsurface.modelsvector3f)
11177                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11178                 if (rsurface.modeltvector3f)
11179                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11180                 if (rsurface.modelnormal3f)
11181                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11182                 if (rsurface.modellightmapcolor4f)
11183                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11184                 if (rsurface.modeltexcoordtexture2f)
11185                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11186                 if (rsurface.modeltexcoordlightmap2f)
11187                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11188         }
11189 }
11190
11191 float RSurf_FogPoint(const float *v)
11192 {
11193         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11194         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11195         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11196         float FogHeightFade = r_refdef.fogheightfade;
11197         float fogfrac;
11198         unsigned int fogmasktableindex;
11199         if (r_refdef.fogplaneviewabove)
11200                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11201         else
11202                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11203         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11204         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11205 }
11206
11207 float RSurf_FogVertex(const float *v)
11208 {
11209         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11210         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11211         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11212         float FogHeightFade = rsurface.fogheightfade;
11213         float fogfrac;
11214         unsigned int fogmasktableindex;
11215         if (r_refdef.fogplaneviewabove)
11216                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11217         else
11218                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11219         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11220         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11221 }
11222
11223 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11224 {
11225         int i;
11226         for (i = 0;i < numelements;i++)
11227                 outelement3i[i] = inelement3i[i] + adjust;
11228 }
11229
11230 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11231 extern cvar_t gl_vbo;
11232 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11233 {
11234         int deformindex;
11235         int firsttriangle;
11236         int numtriangles;
11237         int firstvertex;
11238         int endvertex;
11239         int numvertices;
11240         int surfacefirsttriangle;
11241         int surfacenumtriangles;
11242         int surfacefirstvertex;
11243         int surfaceendvertex;
11244         int surfacenumvertices;
11245         int surfaceadjustvertex;
11246         int needsupdate;
11247         int i, j;
11248         qboolean gaps;
11249         qboolean dynamicvertex;
11250         float amplitude;
11251         float animpos;
11252         float scale;
11253         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11254         float waveparms[4];
11255         q3shaderinfo_deform_t *deform;
11256         const msurface_t *surface, *firstsurface;
11257         r_vertexposition_t *vertexposition;
11258         r_vertexmesh_t *vertexmesh;
11259         if (!texturenumsurfaces)
11260                 return;
11261         // find vertex range of this surface batch
11262         gaps = false;
11263         firstsurface = texturesurfacelist[0];
11264         firsttriangle = firstsurface->num_firsttriangle;
11265         numtriangles = 0;
11266         firstvertex = endvertex = firstsurface->num_firstvertex;
11267         for (i = 0;i < texturenumsurfaces;i++)
11268         {
11269                 surface = texturesurfacelist[i];
11270                 if (surface != firstsurface + i)
11271                         gaps = true;
11272                 surfacefirstvertex = surface->num_firstvertex;
11273                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11274                 surfacenumtriangles = surface->num_triangles;
11275                 if (firstvertex > surfacefirstvertex)
11276                         firstvertex = surfacefirstvertex;
11277                 if (endvertex < surfaceendvertex)
11278                         endvertex = surfaceendvertex;
11279                 numtriangles += surfacenumtriangles;
11280         }
11281         if (!numtriangles)
11282                 return;
11283
11284         // we now know the vertex range used, and if there are any gaps in it
11285         rsurface.batchfirstvertex = firstvertex;
11286         rsurface.batchnumvertices = endvertex - firstvertex;
11287         rsurface.batchfirsttriangle = firsttriangle;
11288         rsurface.batchnumtriangles = numtriangles;
11289
11290         // this variable holds flags for which properties have been updated that
11291         // may require regenerating vertexmesh or vertexposition arrays...
11292         needsupdate = 0;
11293
11294         // check if any dynamic vertex processing must occur
11295         dynamicvertex = false;
11296
11297         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11298                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11299         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11300         {
11301                 switch (deform->deform)
11302                 {
11303                 default:
11304                 case Q3DEFORM_PROJECTIONSHADOW:
11305                 case Q3DEFORM_TEXT0:
11306                 case Q3DEFORM_TEXT1:
11307                 case Q3DEFORM_TEXT2:
11308                 case Q3DEFORM_TEXT3:
11309                 case Q3DEFORM_TEXT4:
11310                 case Q3DEFORM_TEXT5:
11311                 case Q3DEFORM_TEXT6:
11312                 case Q3DEFORM_TEXT7:
11313                 case Q3DEFORM_NONE:
11314                         break;
11315                 case Q3DEFORM_AUTOSPRITE:
11316                         dynamicvertex = true;
11317                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11318                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11319                         break;
11320                 case Q3DEFORM_AUTOSPRITE2:
11321                         dynamicvertex = true;
11322                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11323                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11324                         break;
11325                 case Q3DEFORM_NORMAL:
11326                         dynamicvertex = true;
11327                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11328                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11329                         break;
11330                 case Q3DEFORM_WAVE:
11331                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11332                                 break; // if wavefunc is a nop, ignore this transform
11333                         dynamicvertex = true;
11334                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11335                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11336                         break;
11337                 case Q3DEFORM_BULGE:
11338                         dynamicvertex = true;
11339                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11340                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11341                         break;
11342                 case Q3DEFORM_MOVE:
11343                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11344                                 break; // if wavefunc is a nop, ignore this transform
11345                         dynamicvertex = true;
11346                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11347                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11348                         break;
11349                 }
11350         }
11351         switch(rsurface.texture->tcgen.tcgen)
11352         {
11353         default:
11354         case Q3TCGEN_TEXTURE:
11355                 break;
11356         case Q3TCGEN_LIGHTMAP:
11357                 dynamicvertex = true;
11358                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11359                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11360                 break;
11361         case Q3TCGEN_VECTOR:
11362                 dynamicvertex = true;
11363                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11364                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11365                 break;
11366         case Q3TCGEN_ENVIRONMENT:
11367                 dynamicvertex = true;
11368                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11369                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11370                 break;
11371         }
11372         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11373         {
11374                 dynamicvertex = true;
11375                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11376                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11377         }
11378
11379         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11380         {
11381                 dynamicvertex = true;
11382                 batchneed |= BATCHNEED_NOGAPS;
11383                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11384         }
11385
11386         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11387         {
11388                 dynamicvertex = true;
11389                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11390                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11391         }
11392
11393         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11394         {
11395                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11396                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11397                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11398                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11399                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11400                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11401                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11402         }
11403
11404         // when the model data has no vertex buffer (dynamic mesh), we need to
11405         // eliminate gaps
11406         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
11407                 batchneed |= BATCHNEED_NOGAPS;
11408
11409         // if needsupdate, we have to do a dynamic vertex batch for sure
11410         if (needsupdate & batchneed)
11411                 dynamicvertex = true;
11412
11413         // see if we need to build vertexmesh from arrays
11414         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11415                 dynamicvertex = true;
11416
11417         // see if we need to build vertexposition from arrays
11418         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11419                 dynamicvertex = true;
11420
11421         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11422         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11423                 dynamicvertex = true;
11424
11425         // if there is a chance of animated vertex colors, it's a dynamic batch
11426         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11427                 dynamicvertex = true;
11428
11429         rsurface.batchvertex3f = rsurface.modelvertex3f;
11430         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11431         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11432         rsurface.batchsvector3f = rsurface.modelsvector3f;
11433         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11434         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11435         rsurface.batchtvector3f = rsurface.modeltvector3f;
11436         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11437         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11438         rsurface.batchnormal3f = rsurface.modelnormal3f;
11439         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11440         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11441         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11442         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11443         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11444         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11445         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11446         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11447         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11448         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11449         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11450         rsurface.batchvertexposition = rsurface.modelvertexposition;
11451         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11452         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11453         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11454         rsurface.batchelement3i = rsurface.modelelement3i;
11455         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11456         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11457         rsurface.batchelement3s = rsurface.modelelement3s;
11458         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11459         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11460
11461         // if any dynamic vertex processing has to occur in software, we copy the
11462         // entire surface list together before processing to rebase the vertices
11463         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11464         //
11465         // if any gaps exist and we do not have a static vertex buffer, we have to
11466         // copy the surface list together to avoid wasting upload bandwidth on the
11467         // vertices in the gaps.
11468         //
11469         // if gaps exist and we have a static vertex buffer, we still have to
11470         // combine the index buffer ranges into one dynamic index buffer.
11471         //
11472         // in all cases we end up with data that can be drawn in one call.
11473
11474         if (!dynamicvertex)
11475         {
11476                 // static vertex data, just set pointers...
11477                 rsurface.batchgeneratedvertex = false;
11478                 // if there are gaps, we want to build a combined index buffer,
11479                 // otherwise use the original static buffer with an appropriate offset
11480                 if (gaps)
11481                 {
11482                         firsttriangle = 0;
11483                         numtriangles = 0;
11484                         for (i = 0;i < texturenumsurfaces;i++)
11485                         {
11486                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11487                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11488                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11489                                 numtriangles += surfacenumtriangles;
11490                         }
11491                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11492                         rsurface.batchelement3i_indexbuffer = NULL;
11493                         rsurface.batchelement3i_bufferoffset = 0;
11494                         rsurface.batchelement3s = NULL;
11495                         rsurface.batchelement3s_indexbuffer = NULL;
11496                         rsurface.batchelement3s_bufferoffset = 0;
11497                         if (endvertex <= 65536)
11498                         {
11499                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11500                                 for (i = 0;i < numtriangles*3;i++)
11501                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11502                         }
11503                         rsurface.batchfirsttriangle = firsttriangle;
11504                         rsurface.batchnumtriangles = numtriangles;
11505                 }
11506                 return;
11507         }
11508
11509         // something needs software processing, do it for real...
11510         // we only directly handle interleaved array data in this case...
11511         rsurface.batchgeneratedvertex = true;
11512
11513         // now copy the vertex data into a combined array and make an index array
11514         // (this is what Quake3 does all the time)
11515         //if (gaps || rsurface.batchfirstvertex)
11516         {
11517                 rsurface.batchvertexposition = NULL;
11518                 rsurface.batchvertexpositionbuffer = NULL;
11519                 rsurface.batchvertexmesh = NULL;
11520                 rsurface.batchvertexmeshbuffer = NULL;
11521                 rsurface.batchvertex3f = NULL;
11522                 rsurface.batchvertex3f_vertexbuffer = NULL;
11523                 rsurface.batchvertex3f_bufferoffset = 0;
11524                 rsurface.batchsvector3f = NULL;
11525                 rsurface.batchsvector3f_vertexbuffer = NULL;
11526                 rsurface.batchsvector3f_bufferoffset = 0;
11527                 rsurface.batchtvector3f = NULL;
11528                 rsurface.batchtvector3f_vertexbuffer = NULL;
11529                 rsurface.batchtvector3f_bufferoffset = 0;
11530                 rsurface.batchnormal3f = NULL;
11531                 rsurface.batchnormal3f_vertexbuffer = NULL;
11532                 rsurface.batchnormal3f_bufferoffset = 0;
11533                 rsurface.batchlightmapcolor4f = NULL;
11534                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11535                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11536                 rsurface.batchtexcoordtexture2f = NULL;
11537                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11538                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11539                 rsurface.batchtexcoordlightmap2f = NULL;
11540                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11541                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11542                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11543                 rsurface.batchelement3i_indexbuffer = NULL;
11544                 rsurface.batchelement3i_bufferoffset = 0;
11545                 rsurface.batchelement3s = NULL;
11546                 rsurface.batchelement3s_indexbuffer = NULL;
11547                 rsurface.batchelement3s_bufferoffset = 0;
11548                 // we'll only be setting up certain arrays as needed
11549                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11550                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11551                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11552                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11553                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11554                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11555                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11556                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11557                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11558                 {
11559                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11560                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11561                 }
11562                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11563                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11564                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11565                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11566                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11567                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11568                 numvertices = 0;
11569                 numtriangles = 0;
11570                 for (i = 0;i < texturenumsurfaces;i++)
11571                 {
11572                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11573                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11574                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11575                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11576                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11577                         // copy only the data requested
11578                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11579                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11580                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11581                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11582                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11583                         {
11584                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11585                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11586                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11587                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11588                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11589                                 {
11590                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11591                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11592                                 }
11593                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11594                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11595                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11596                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11597                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11598                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11599                         }
11600                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11601                         numvertices += surfacenumvertices;
11602                         numtriangles += surfacenumtriangles;
11603                 }
11604
11605                 // generate a 16bit index array as well if possible
11606                 // (in general, dynamic batches fit)
11607                 if (numvertices <= 65536)
11608                 {
11609                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11610                         for (i = 0;i < numtriangles*3;i++)
11611                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11612                 }
11613
11614                 // since we've copied everything, the batch now starts at 0
11615                 rsurface.batchfirstvertex = 0;
11616                 rsurface.batchnumvertices = numvertices;
11617                 rsurface.batchfirsttriangle = 0;
11618                 rsurface.batchnumtriangles = numtriangles;
11619         }
11620
11621         // q1bsp surfaces rendered in vertex color mode have to have colors
11622         // calculated based on lightstyles
11623         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11624         {
11625                 // generate color arrays for the surfaces in this list
11626                 int c[4];
11627                 int scale;
11628                 int size3;
11629                 const int *offsets;
11630                 const unsigned char *lm;
11631                 numvertices = 0;
11632                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11633                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11634                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11635                 for (i = 0;i < texturenumsurfaces;i++)
11636                 {
11637                         surface = texturesurfacelist[i];
11638                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11639                         surfacenumvertices = surface->num_vertices;
11640                         if (surface->lightmapinfo->samples)
11641                         {
11642                                 for (j = 0;j < surfacenumvertices;j++)
11643                                 {
11644                                         lm = surface->lightmapinfo->samples + offsets[j];
11645                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11646                                         VectorScale(lm, scale, c);
11647                                         if (surface->lightmapinfo->styles[1] != 255)
11648                                         {
11649                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11650                                                 lm += size3;
11651                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11652                                                 VectorMA(c, scale, lm, c);
11653                                                 if (surface->lightmapinfo->styles[2] != 255)
11654                                                 {
11655                                                         lm += size3;
11656                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11657                                                         VectorMA(c, scale, lm, c);
11658                                                         if (surface->lightmapinfo->styles[3] != 255)
11659                                                         {
11660                                                                 lm += size3;
11661                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11662                                                                 VectorMA(c, scale, lm, c);
11663                                                         }
11664                                                 }
11665                                         }
11666                                         c[0] >>= 15;
11667                                         c[1] >>= 15;
11668                                         c[2] >>= 15;
11669                                         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);
11670                                         numvertices++;
11671                                 }
11672                         }
11673                         else
11674                         {
11675                                 for (j = 0;j < surfacenumvertices;j++)
11676                                 {
11677                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11678                                         numvertices++;
11679                                 }
11680                         }
11681                 }
11682         }
11683
11684         // if vertices are deformed (sprite flares and things in maps, possibly
11685         // water waves, bulges and other deformations), modify the copied vertices
11686         // in place
11687         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11688         {
11689                 switch (deform->deform)
11690                 {
11691                 default:
11692                 case Q3DEFORM_PROJECTIONSHADOW:
11693                 case Q3DEFORM_TEXT0:
11694                 case Q3DEFORM_TEXT1:
11695                 case Q3DEFORM_TEXT2:
11696                 case Q3DEFORM_TEXT3:
11697                 case Q3DEFORM_TEXT4:
11698                 case Q3DEFORM_TEXT5:
11699                 case Q3DEFORM_TEXT6:
11700                 case Q3DEFORM_TEXT7:
11701                 case Q3DEFORM_NONE:
11702                         break;
11703                 case Q3DEFORM_AUTOSPRITE:
11704                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11705                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11706                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11707                         VectorNormalize(newforward);
11708                         VectorNormalize(newright);
11709                         VectorNormalize(newup);
11710                         // a single autosprite surface can contain multiple sprites...
11711                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11712                         {
11713                                 VectorClear(center);
11714                                 for (i = 0;i < 4;i++)
11715                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11716                                 VectorScale(center, 0.25f, center);
11717                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11718                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11719                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11720                                 for (i = 0;i < 4;i++)
11721                                 {
11722                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11723                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11724                                 }
11725                         }
11726                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11727                         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);
11728                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11729                         rsurface.batchvertex3f_vertexbuffer = NULL;
11730                         rsurface.batchvertex3f_bufferoffset = 0;
11731                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11732                         rsurface.batchsvector3f_vertexbuffer = NULL;
11733                         rsurface.batchsvector3f_bufferoffset = 0;
11734                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11735                         rsurface.batchtvector3f_vertexbuffer = NULL;
11736                         rsurface.batchtvector3f_bufferoffset = 0;
11737                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11738                         rsurface.batchnormal3f_vertexbuffer = NULL;
11739                         rsurface.batchnormal3f_bufferoffset = 0;
11740                         break;
11741                 case Q3DEFORM_AUTOSPRITE2:
11742                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11743                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11744                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11745                         VectorNormalize(newforward);
11746                         VectorNormalize(newright);
11747                         VectorNormalize(newup);
11748                         {
11749                                 const float *v1, *v2;
11750                                 vec3_t start, end;
11751                                 float f, l;
11752                                 struct
11753                                 {
11754                                         float length2;
11755                                         const float *v1;
11756                                         const float *v2;
11757                                 }
11758                                 shortest[2];
11759                                 memset(shortest, 0, sizeof(shortest));
11760                                 // a single autosprite surface can contain multiple sprites...
11761                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11762                                 {
11763                                         VectorClear(center);
11764                                         for (i = 0;i < 4;i++)
11765                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11766                                         VectorScale(center, 0.25f, center);
11767                                         // find the two shortest edges, then use them to define the
11768                                         // axis vectors for rotating around the central axis
11769                                         for (i = 0;i < 6;i++)
11770                                         {
11771                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11772                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11773                                                 l = VectorDistance2(v1, v2);
11774                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11775                                                 if (v1[2] != v2[2])
11776                                                         l += (1.0f / 1024.0f);
11777                                                 if (shortest[0].length2 > l || i == 0)
11778                                                 {
11779                                                         shortest[1] = shortest[0];
11780                                                         shortest[0].length2 = l;
11781                                                         shortest[0].v1 = v1;
11782                                                         shortest[0].v2 = v2;
11783                                                 }
11784                                                 else if (shortest[1].length2 > l || i == 1)
11785                                                 {
11786                                                         shortest[1].length2 = l;
11787                                                         shortest[1].v1 = v1;
11788                                                         shortest[1].v2 = v2;
11789                                                 }
11790                                         }
11791                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11792                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11793                                         // this calculates the right vector from the shortest edge
11794                                         // and the up vector from the edge midpoints
11795                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11796                                         VectorNormalize(right);
11797                                         VectorSubtract(end, start, up);
11798                                         VectorNormalize(up);
11799                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11800                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11801                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11802                                         VectorNegate(forward, forward);
11803                                         VectorReflect(forward, 0, up, forward);
11804                                         VectorNormalize(forward);
11805                                         CrossProduct(up, forward, newright);
11806                                         VectorNormalize(newright);
11807                                         // rotate the quad around the up axis vector, this is made
11808                                         // especially easy by the fact we know the quad is flat,
11809                                         // so we only have to subtract the center position and
11810                                         // measure distance along the right vector, and then
11811                                         // multiply that by the newright vector and add back the
11812                                         // center position
11813                                         // we also need to subtract the old position to undo the
11814                                         // displacement from the center, which we do with a
11815                                         // DotProduct, the subtraction/addition of center is also
11816                                         // optimized into DotProducts here
11817                                         l = DotProduct(right, center);
11818                                         for (i = 0;i < 4;i++)
11819                                         {
11820                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11821                                                 f = DotProduct(right, v1) - l;
11822                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11823                                         }
11824                                 }
11825                         }
11826                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11827                         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);
11828                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11829                         rsurface.batchvertex3f_vertexbuffer = NULL;
11830                         rsurface.batchvertex3f_bufferoffset = 0;
11831                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11832                         rsurface.batchsvector3f_vertexbuffer = NULL;
11833                         rsurface.batchsvector3f_bufferoffset = 0;
11834                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11835                         rsurface.batchtvector3f_vertexbuffer = NULL;
11836                         rsurface.batchtvector3f_bufferoffset = 0;
11837                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11838                         rsurface.batchnormal3f_vertexbuffer = NULL;
11839                         rsurface.batchnormal3f_bufferoffset = 0;
11840                         break;
11841                 case Q3DEFORM_NORMAL:
11842                         // deform the normals to make reflections wavey
11843                         for (j = 0;j < rsurface.batchnumvertices;j++)
11844                         {
11845                                 float vertex[3];
11846                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11847                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11848                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11849                                 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]);
11850                                 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]);
11851                                 VectorNormalize(normal);
11852                         }
11853                         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);
11854                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11855                         rsurface.batchsvector3f_vertexbuffer = NULL;
11856                         rsurface.batchsvector3f_bufferoffset = 0;
11857                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11858                         rsurface.batchtvector3f_vertexbuffer = NULL;
11859                         rsurface.batchtvector3f_bufferoffset = 0;
11860                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11861                         rsurface.batchnormal3f_vertexbuffer = NULL;
11862                         rsurface.batchnormal3f_bufferoffset = 0;
11863                         break;
11864                 case Q3DEFORM_WAVE:
11865                         // deform vertex array to make wavey water and flags and such
11866                         waveparms[0] = deform->waveparms[0];
11867                         waveparms[1] = deform->waveparms[1];
11868                         waveparms[2] = deform->waveparms[2];
11869                         waveparms[3] = deform->waveparms[3];
11870                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11871                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11872                         // this is how a divisor of vertex influence on deformation
11873                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11874                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11875                         for (j = 0;j < rsurface.batchnumvertices;j++)
11876                         {
11877                                 // if the wavefunc depends on time, evaluate it per-vertex
11878                                 if (waveparms[3])
11879                                 {
11880                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11881                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11882                                 }
11883                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11884                         }
11885                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11886                         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);
11887                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11888                         rsurface.batchvertex3f_vertexbuffer = NULL;
11889                         rsurface.batchvertex3f_bufferoffset = 0;
11890                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11891                         rsurface.batchsvector3f_vertexbuffer = NULL;
11892                         rsurface.batchsvector3f_bufferoffset = 0;
11893                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11894                         rsurface.batchtvector3f_vertexbuffer = NULL;
11895                         rsurface.batchtvector3f_bufferoffset = 0;
11896                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11897                         rsurface.batchnormal3f_vertexbuffer = NULL;
11898                         rsurface.batchnormal3f_bufferoffset = 0;
11899                         break;
11900                 case Q3DEFORM_BULGE:
11901                         // deform vertex array to make the surface have moving bulges
11902                         for (j = 0;j < rsurface.batchnumvertices;j++)
11903                         {
11904                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11905                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11906                         }
11907                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11908                         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);
11909                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11910                         rsurface.batchvertex3f_vertexbuffer = NULL;
11911                         rsurface.batchvertex3f_bufferoffset = 0;
11912                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11913                         rsurface.batchsvector3f_vertexbuffer = NULL;
11914                         rsurface.batchsvector3f_bufferoffset = 0;
11915                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11916                         rsurface.batchtvector3f_vertexbuffer = NULL;
11917                         rsurface.batchtvector3f_bufferoffset = 0;
11918                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11919                         rsurface.batchnormal3f_vertexbuffer = NULL;
11920                         rsurface.batchnormal3f_bufferoffset = 0;
11921                         break;
11922                 case Q3DEFORM_MOVE:
11923                         // deform vertex array
11924                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11925                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11926                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11927                         VectorScale(deform->parms, scale, waveparms);
11928                         for (j = 0;j < rsurface.batchnumvertices;j++)
11929                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11930                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11931                         rsurface.batchvertex3f_vertexbuffer = NULL;
11932                         rsurface.batchvertex3f_bufferoffset = 0;
11933                         break;
11934                 }
11935         }
11936
11937         // generate texcoords based on the chosen texcoord source
11938         switch(rsurface.texture->tcgen.tcgen)
11939         {
11940         default:
11941         case Q3TCGEN_TEXTURE:
11942                 break;
11943         case Q3TCGEN_LIGHTMAP:
11944                 if (rsurface.batchtexcoordlightmap2f)
11945                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11946                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11947                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11948                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11949                 break;
11950         case Q3TCGEN_VECTOR:
11951                 for (j = 0;j < rsurface.batchnumvertices;j++)
11952                 {
11953                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11954                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11955                 }
11956                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11957                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11958                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11959                 break;
11960         case Q3TCGEN_ENVIRONMENT:
11961                 // make environment reflections using a spheremap
11962                 for (j = 0;j < rsurface.batchnumvertices;j++)
11963                 {
11964                         // identical to Q3A's method, but executed in worldspace so
11965                         // carried models can be shiny too
11966
11967                         float viewer[3], d, reflected[3], worldreflected[3];
11968
11969                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11970                         // VectorNormalize(viewer);
11971
11972                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11973
11974                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11975                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11976                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11977                         // note: this is proportinal to viewer, so we can normalize later
11978
11979                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11980                         VectorNormalize(worldreflected);
11981
11982                         // note: this sphere map only uses world x and z!
11983                         // so positive and negative y will LOOK THE SAME.
11984                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11985                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11986                 }
11987                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11988                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11989                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11990                 break;
11991         }
11992         // the only tcmod that needs software vertex processing is turbulent, so
11993         // check for it here and apply the changes if needed
11994         // and we only support that as the first one
11995         // (handling a mixture of turbulent and other tcmods would be problematic
11996         //  without punting it entirely to a software path)
11997         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11998         {
11999                 amplitude = rsurface.texture->tcmods[0].parms[1];
12000                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12001                 for (j = 0;j < rsurface.batchnumvertices;j++)
12002                 {
12003                         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);
12004                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12005                 }
12006                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12007                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12008                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12009         }
12010
12011         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12012         {
12013                 // convert the modified arrays to vertex structs
12014                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12015                 rsurface.batchvertexmeshbuffer = NULL;
12016                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12017                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12018                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12019                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12020                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12021                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12022                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12023                 {
12024                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12025                         {
12026                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12027                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12028                         }
12029                 }
12030                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12031                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12032                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12033                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12034                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12035                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12036                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12037                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12038                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12039         }
12040
12041         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12042         {
12043                 // convert the modified arrays to vertex structs
12044                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12045                 rsurface.batchvertexpositionbuffer = NULL;
12046                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12047                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12048                 else
12049                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12050                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12051         }
12052 }
12053
12054 void RSurf_DrawBatch(void)
12055 {
12056         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);
12057 }
12058
12059 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12060 {
12061         // pick the closest matching water plane
12062         int planeindex, vertexindex, bestplaneindex = -1;
12063         float d, bestd;
12064         vec3_t vert;
12065         const float *v;
12066         r_waterstate_waterplane_t *p;
12067         bestd = 0;
12068         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12069         {
12070                 if(p->camera_entity != rsurface.texture->camera_entity)
12071                         continue;
12072                 d = 0;
12073                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12074                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12075                 {
12076                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12077                         d += fabs(PlaneDiff(vert, &p->plane));
12078                 }
12079                 if (bestd > d || bestplaneindex < 0)
12080                 {
12081                         bestd = d;
12082                         bestplaneindex = planeindex;
12083                 }
12084         }
12085         return bestplaneindex;
12086 }
12087
12088 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12089 {
12090         int i;
12091         for (i = 0;i < rsurface.batchnumvertices;i++)
12092                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12093         rsurface.passcolor4f = rsurface.array_passcolor4f;
12094         rsurface.passcolor4f_vertexbuffer = 0;
12095         rsurface.passcolor4f_bufferoffset = 0;
12096 }
12097
12098 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12099 {
12100         int i;
12101         float f;
12102         const float *v;
12103         const float *c;
12104         float *c2;
12105         if (rsurface.passcolor4f)
12106         {
12107                 // generate color arrays
12108                 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)
12109                 {
12110                         f = RSurf_FogVertex(v);
12111                         c2[0] = c[0] * f;
12112                         c2[1] = c[1] * f;
12113                         c2[2] = c[2] * f;
12114                         c2[3] = c[3];
12115                 }
12116         }
12117         else
12118         {
12119                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12120                 {
12121                         f = RSurf_FogVertex(v);
12122                         c2[0] = f;
12123                         c2[1] = f;
12124                         c2[2] = f;
12125                         c2[3] = 1;
12126                 }
12127         }
12128         rsurface.passcolor4f = rsurface.array_passcolor4f;
12129         rsurface.passcolor4f_vertexbuffer = 0;
12130         rsurface.passcolor4f_bufferoffset = 0;
12131 }
12132
12133 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12134 {
12135         int i;
12136         float f;
12137         const float *v;
12138         const float *c;
12139         float *c2;
12140         if (!rsurface.passcolor4f)
12141                 return;
12142         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)
12143         {
12144                 f = RSurf_FogVertex(v);
12145                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12146                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12147                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12148                 c2[3] = c[3];
12149         }
12150         rsurface.passcolor4f = rsurface.array_passcolor4f;
12151         rsurface.passcolor4f_vertexbuffer = 0;
12152         rsurface.passcolor4f_bufferoffset = 0;
12153 }
12154
12155 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12156 {
12157         int i;
12158         const float *c;
12159         float *c2;
12160         if (!rsurface.passcolor4f)
12161                 return;
12162         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12163         {
12164                 c2[0] = c[0] * r;
12165                 c2[1] = c[1] * g;
12166                 c2[2] = c[2] * b;
12167                 c2[3] = c[3] * a;
12168         }
12169         rsurface.passcolor4f = rsurface.array_passcolor4f;
12170         rsurface.passcolor4f_vertexbuffer = 0;
12171         rsurface.passcolor4f_bufferoffset = 0;
12172 }
12173
12174 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12175 {
12176         int i;
12177         const float *c;
12178         float *c2;
12179         if (!rsurface.passcolor4f)
12180                 return;
12181         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12182         {
12183                 c2[0] = c[0] + r_refdef.scene.ambient;
12184                 c2[1] = c[1] + r_refdef.scene.ambient;
12185                 c2[2] = c[2] + r_refdef.scene.ambient;
12186                 c2[3] = c[3];
12187         }
12188         rsurface.passcolor4f = rsurface.array_passcolor4f;
12189         rsurface.passcolor4f_vertexbuffer = 0;
12190         rsurface.passcolor4f_bufferoffset = 0;
12191 }
12192
12193 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12194 {
12195         // TODO: optimize
12196         rsurface.passcolor4f = NULL;
12197         rsurface.passcolor4f_vertexbuffer = 0;
12198         rsurface.passcolor4f_bufferoffset = 0;
12199         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12200         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12201         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12202         GL_Color(r, g, b, a);
12203         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12204         RSurf_DrawBatch();
12205 }
12206
12207 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12208 {
12209         // TODO: optimize applyfog && applycolor case
12210         // just apply fog if necessary, and tint the fog color array if necessary
12211         rsurface.passcolor4f = NULL;
12212         rsurface.passcolor4f_vertexbuffer = 0;
12213         rsurface.passcolor4f_bufferoffset = 0;
12214         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12215         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12216         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12217         GL_Color(r, g, b, a);
12218         RSurf_DrawBatch();
12219 }
12220
12221 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12222 {
12223         // TODO: optimize
12224         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12225         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12226         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12227         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12228         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12229         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12230         GL_Color(r, g, b, a);
12231         RSurf_DrawBatch();
12232 }
12233
12234 static void RSurf_DrawBatch_GL11_ClampColor(void)
12235 {
12236         int i;
12237         const float *c1;
12238         float *c2;
12239         if (!rsurface.passcolor4f)
12240                 return;
12241         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12242         {
12243                 c2[0] = bound(0.0f, c1[0], 1.0f);
12244                 c2[1] = bound(0.0f, c1[1], 1.0f);
12245                 c2[2] = bound(0.0f, c1[2], 1.0f);
12246                 c2[3] = bound(0.0f, c1[3], 1.0f);
12247         }
12248 }
12249
12250 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12251 {
12252         int i;
12253         float f;
12254         float alpha;
12255         const float *v;
12256         const float *n;
12257         float *c;
12258         vec3_t ambientcolor;
12259         vec3_t diffusecolor;
12260         vec3_t lightdir;
12261         // TODO: optimize
12262         // model lighting
12263         VectorCopy(rsurface.modellight_lightdir, lightdir);
12264         f = 0.5f * r_refdef.lightmapintensity;
12265         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12266         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12267         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12268         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12269         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12270         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12271         alpha = *a;
12272         if (VectorLength2(diffusecolor) > 0)
12273         {
12274                 // q3-style directional shading
12275                 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)
12276                 {
12277                         if ((f = DotProduct(n, lightdir)) > 0)
12278                                 VectorMA(ambientcolor, f, diffusecolor, c);
12279                         else
12280                                 VectorCopy(ambientcolor, c);
12281                         c[3] = alpha;
12282                 }
12283                 *r = 1;
12284                 *g = 1;
12285                 *b = 1;
12286                 *a = 1;
12287                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12288                 rsurface.passcolor4f_vertexbuffer = 0;
12289                 rsurface.passcolor4f_bufferoffset = 0;
12290                 *applycolor = false;
12291         }
12292         else
12293         {
12294                 *r = ambientcolor[0];
12295                 *g = ambientcolor[1];
12296                 *b = ambientcolor[2];
12297                 rsurface.passcolor4f = NULL;
12298                 rsurface.passcolor4f_vertexbuffer = 0;
12299                 rsurface.passcolor4f_bufferoffset = 0;
12300         }
12301 }
12302
12303 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12304 {
12305         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12306         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12307         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12308         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12309         GL_Color(r, g, b, a);
12310         RSurf_DrawBatch();
12311 }
12312
12313 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12314 {
12315         int i;
12316         float f;
12317         const float *v;
12318         float *c;
12319         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12320         {
12321                 f = 1 - RSurf_FogVertex(v);
12322                 c[0] = r;
12323                 c[1] = g;
12324                 c[2] = b;
12325                 c[3] = f * a;
12326         }
12327 }
12328
12329 void RSurf_SetupDepthAndCulling(void)
12330 {
12331         // submodels are biased to avoid z-fighting with world surfaces that they
12332         // may be exactly overlapping (avoids z-fighting artifacts on certain
12333         // doors and things in Quake maps)
12334         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12335         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12336         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12337         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12338 }
12339
12340 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12341 {
12342         // transparent sky would be ridiculous
12343         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12344                 return;
12345         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12346         skyrenderlater = true;
12347         RSurf_SetupDepthAndCulling();
12348         GL_DepthMask(true);
12349         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12350         // skymasking on them, and Quake3 never did sky masking (unlike
12351         // software Quake and software Quake2), so disable the sky masking
12352         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12353         // and skymasking also looks very bad when noclipping outside the
12354         // level, so don't use it then either.
12355         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12356         {
12357                 R_Mesh_ResetTextureState();
12358                 if (skyrendermasked)
12359                 {
12360                         R_SetupShader_DepthOrShadow();
12361                         // depth-only (masking)
12362                         GL_ColorMask(0,0,0,0);
12363                         // just to make sure that braindead drivers don't draw
12364                         // anything despite that colormask...
12365                         GL_BlendFunc(GL_ZERO, GL_ONE);
12366                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12367                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12368                 }
12369                 else
12370                 {
12371                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12372                         // fog sky
12373                         GL_BlendFunc(GL_ONE, GL_ZERO);
12374                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12375                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12376                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12377                 }
12378                 RSurf_DrawBatch();
12379                 if (skyrendermasked)
12380                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12381         }
12382         R_Mesh_ResetTextureState();
12383         GL_Color(1, 1, 1, 1);
12384 }
12385
12386 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12387 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12388 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12389 {
12390         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12391                 return;
12392         if (prepass)
12393         {
12394                 // render screenspace normalmap to texture
12395                 GL_DepthMask(true);
12396                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12397                 RSurf_DrawBatch();
12398                 return;
12399         }
12400
12401         // bind lightmap texture
12402
12403         // water/refraction/reflection/camera surfaces have to be handled specially
12404         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12405         {
12406                 int start, end, startplaneindex;
12407                 for (start = 0;start < texturenumsurfaces;start = end)
12408                 {
12409                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12410                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12411                                 ;
12412                         // now that we have a batch using the same planeindex, render it
12413                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12414                         {
12415                                 // render water or distortion background
12416                                 GL_DepthMask(true);
12417                                 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));
12418                                 RSurf_DrawBatch();
12419                                 // blend surface on top
12420                                 GL_DepthMask(false);
12421                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12422                                 RSurf_DrawBatch();
12423                         }
12424                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12425                         {
12426                                 // render surface with reflection texture as input
12427                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12428                                 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));
12429                                 RSurf_DrawBatch();
12430                         }
12431                 }
12432                 return;
12433         }
12434
12435         // render surface batch normally
12436         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12437         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12438         RSurf_DrawBatch();
12439 }
12440
12441 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12442 {
12443         // OpenGL 1.3 path - anything not completely ancient
12444         qboolean applycolor;
12445         qboolean applyfog;
12446         int layerindex;
12447         const texturelayer_t *layer;
12448         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);
12449         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12450
12451         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12452         {
12453                 vec4_t layercolor;
12454                 int layertexrgbscale;
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                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12468                 {
12469                         layertexrgbscale = 4;
12470                         VectorScale(layer->color, 0.25f, layercolor);
12471                 }
12472                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12473                 {
12474                         layertexrgbscale = 2;
12475                         VectorScale(layer->color, 0.5f, layercolor);
12476                 }
12477                 else
12478                 {
12479                         layertexrgbscale = 1;
12480                         VectorScale(layer->color, 1.0f, layercolor);
12481                 }
12482                 layercolor[3] = layer->color[3];
12483                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12484                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12485                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12486                 switch (layer->type)
12487                 {
12488                 case TEXTURELAYERTYPE_LITTEXTURE:
12489                         // single-pass lightmapped texture with 2x rgbscale
12490                         R_Mesh_TexBind(0, r_texture_white);
12491                         R_Mesh_TexMatrix(0, NULL);
12492                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12493                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12494                         R_Mesh_TexBind(1, layer->texture);
12495                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12496                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12497                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12498                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12499                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12500                         else if (rsurface.uselightmaptexture)
12501                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12502                         else
12503                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12504                         break;
12505                 case TEXTURELAYERTYPE_TEXTURE:
12506                         // singletexture unlit texture with transparency support
12507                         R_Mesh_TexBind(0, layer->texture);
12508                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12509                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12510                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12511                         R_Mesh_TexBind(1, 0);
12512                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12513                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, 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, layertexrgbscale, 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                         R_Mesh_TexBind(1, 0);
12530                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12531                         // generate a color array for the fog pass
12532                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12533                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12534                         RSurf_DrawBatch();
12535                         break;
12536                 default:
12537                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12538                 }
12539         }
12540         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12541         {
12542                 GL_DepthFunc(GL_LEQUAL);
12543                 GL_AlphaTest(false);
12544         }
12545 }
12546
12547 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12548 {
12549         // OpenGL 1.1 - crusty old voodoo path
12550         qboolean applyfog;
12551         int layerindex;
12552         const texturelayer_t *layer;
12553         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);
12554         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12555
12556         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12557         {
12558                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12559                 {
12560                         if (layerindex == 0)
12561                                 GL_AlphaTest(true);
12562                         else
12563                         {
12564                                 GL_AlphaTest(false);
12565                                 GL_DepthFunc(GL_EQUAL);
12566                         }
12567                 }
12568                 GL_DepthMask(layer->depthmask && writedepth);
12569                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12570                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12571                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12572                 switch (layer->type)
12573                 {
12574                 case TEXTURELAYERTYPE_LITTEXTURE:
12575                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12576                         {
12577                                 // two-pass lit texture with 2x rgbscale
12578                                 // first the lightmap pass
12579                                 R_Mesh_TexBind(0, r_texture_white);
12580                                 R_Mesh_TexMatrix(0, NULL);
12581                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12582                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12583                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12584                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12585                                 else if (rsurface.uselightmaptexture)
12586                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12587                                 else
12588                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12589                                 // then apply the texture to it
12590                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12591                                 R_Mesh_TexBind(0, layer->texture);
12592                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12593                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12594                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12595                                 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);
12596                         }
12597                         else
12598                         {
12599                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12600                                 R_Mesh_TexBind(0, layer->texture);
12601                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12602                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12603                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12604                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12605                                         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);
12606                                 else
12607                                         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);
12608                         }
12609                         break;
12610                 case TEXTURELAYERTYPE_TEXTURE:
12611                         // singletexture unlit texture with transparency support
12612                         R_Mesh_TexBind(0, layer->texture);
12613                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12614                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12615                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12616                         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);
12617                         break;
12618                 case TEXTURELAYERTYPE_FOG:
12619                         // singletexture fogging
12620                         if (layer->texture)
12621                         {
12622                                 R_Mesh_TexBind(0, layer->texture);
12623                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12624                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12625                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12626                         }
12627                         else
12628                         {
12629                                 R_Mesh_TexBind(0, 0);
12630                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12631                         }
12632                         // generate a color array for the fog pass
12633                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12634                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12635                         RSurf_DrawBatch();
12636                         break;
12637                 default:
12638                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12639                 }
12640         }
12641         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12642         {
12643                 GL_DepthFunc(GL_LEQUAL);
12644                 GL_AlphaTest(false);
12645         }
12646 }
12647
12648 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12649 {
12650         int vi;
12651         int j;
12652         r_vertexgeneric_t *batchvertex;
12653         float c[4];
12654
12655         GL_AlphaTest(false);
12656         R_Mesh_ResetTextureState();
12657         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12658
12659         if(rsurface.texture && rsurface.texture->currentskinframe)
12660         {
12661                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12662                 c[3] *= rsurface.texture->currentalpha;
12663         }
12664         else
12665         {
12666                 c[0] = 1;
12667                 c[1] = 0;
12668                 c[2] = 1;
12669                 c[3] = 1;
12670         }
12671
12672         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12673         {
12674                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12675                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12676                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12677         }
12678
12679         // brighten it up (as texture value 127 means "unlit")
12680         c[0] *= 2 * r_refdef.view.colorscale;
12681         c[1] *= 2 * r_refdef.view.colorscale;
12682         c[2] *= 2 * r_refdef.view.colorscale;
12683
12684         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12685                 c[3] *= r_wateralpha.value;
12686
12687         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12688         {
12689                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12690                 GL_DepthMask(false);
12691         }
12692         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12693         {
12694                 GL_BlendFunc(GL_ONE, GL_ONE);
12695                 GL_DepthMask(false);
12696         }
12697         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12698         {
12699                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12700                 GL_DepthMask(false);
12701         }
12702         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12703         {
12704                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12705                 GL_DepthMask(false);
12706         }
12707         else
12708         {
12709                 GL_BlendFunc(GL_ONE, GL_ZERO);
12710                 GL_DepthMask(writedepth);
12711         }
12712
12713         if (r_showsurfaces.integer == 3)
12714         {
12715                 rsurface.passcolor4f = NULL;
12716
12717                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12718                 {
12719                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12720
12721                         rsurface.passcolor4f = NULL;
12722                         rsurface.passcolor4f_vertexbuffer = 0;
12723                         rsurface.passcolor4f_bufferoffset = 0;
12724                 }
12725                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12726                 {
12727                         qboolean applycolor = true;
12728                         float one = 1.0;
12729
12730                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12731
12732                         r_refdef.lightmapintensity = 1;
12733                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12734                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12735                 }
12736                 else
12737                 {
12738                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12739
12740                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12741                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12742                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12743                 }
12744
12745                 if(!rsurface.passcolor4f)
12746                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12747
12748                 RSurf_DrawBatch_GL11_ApplyAmbient();
12749                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12750                 if(r_refdef.fogenabled)
12751                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12752                 RSurf_DrawBatch_GL11_ClampColor();
12753
12754                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12755                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12756                 RSurf_DrawBatch();
12757         }
12758         else if (!r_refdef.view.showdebug)
12759         {
12760                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12761                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12762                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12763                 {
12764                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12765                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12766                 }
12767                 R_Mesh_PrepareVertices_Generic_Unlock();
12768                 RSurf_DrawBatch();
12769         }
12770         else if (r_showsurfaces.integer == 4)
12771         {
12772                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12773                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12774                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12775                 {
12776                         unsigned char c = vi << 3;
12777                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12778                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12779                 }
12780                 R_Mesh_PrepareVertices_Generic_Unlock();
12781                 RSurf_DrawBatch();
12782         }
12783         else if (r_showsurfaces.integer == 2)
12784         {
12785                 const int *e;
12786                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12787                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12788                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12789                 {
12790                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12791                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12792                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12793                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12794                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12795                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12796                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12797                 }
12798                 R_Mesh_PrepareVertices_Generic_Unlock();
12799                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12800         }
12801         else
12802         {
12803                 int texturesurfaceindex;
12804                 int k;
12805                 const msurface_t *surface;
12806                 unsigned char surfacecolor4ub[4];
12807                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12808                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12809                 vi = 0;
12810                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12811                 {
12812                         surface = texturesurfacelist[texturesurfaceindex];
12813                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12814                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12815                         for (j = 0;j < surface->num_vertices;j++)
12816                         {
12817                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12818                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12819                                 vi++;
12820                         }
12821                 }
12822                 R_Mesh_PrepareVertices_Generic_Unlock();
12823                 RSurf_DrawBatch();
12824         }
12825 }
12826
12827 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12828 {
12829         CHECKGLERROR
12830         RSurf_SetupDepthAndCulling();
12831         if (r_showsurfaces.integer)
12832         {
12833                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12834                 return;
12835         }
12836         switch (vid.renderpath)
12837         {
12838         case RENDERPATH_GL20:
12839         case RENDERPATH_CGGL:
12840         case RENDERPATH_D3D9:
12841         case RENDERPATH_D3D10:
12842         case RENDERPATH_D3D11:
12843                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12844                 break;
12845         case RENDERPATH_GL13:
12846                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12847                 break;
12848         case RENDERPATH_GL11:
12849                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12850                 break;
12851         }
12852         CHECKGLERROR
12853 }
12854
12855 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12856 {
12857         CHECKGLERROR
12858         RSurf_SetupDepthAndCulling();
12859         if (r_showsurfaces.integer)
12860         {
12861                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12862                 return;
12863         }
12864         switch (vid.renderpath)
12865         {
12866         case RENDERPATH_GL20:
12867         case RENDERPATH_CGGL:
12868         case RENDERPATH_D3D9:
12869         case RENDERPATH_D3D10:
12870         case RENDERPATH_D3D11:
12871                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12872                 break;
12873         case RENDERPATH_GL13:
12874                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12875                 break;
12876         case RENDERPATH_GL11:
12877                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12878                 break;
12879         }
12880         CHECKGLERROR
12881 }
12882
12883 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12884 {
12885         int i, j;
12886         int texturenumsurfaces, endsurface;
12887         texture_t *texture;
12888         const msurface_t *surface;
12889 #define MAXBATCH_TRANSPARENTSURFACES 256
12890         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12891
12892         // if the model is static it doesn't matter what value we give for
12893         // wantnormals and wanttangents, so this logic uses only rules applicable
12894         // to a model, knowing that they are meaningless otherwise
12895         if (ent == r_refdef.scene.worldentity)
12896                 RSurf_ActiveWorldEntity();
12897         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12898                 RSurf_ActiveModelEntity(ent, false, false, false);
12899         else
12900         {
12901                 switch (vid.renderpath)
12902                 {
12903                 case RENDERPATH_GL20:
12904                 case RENDERPATH_CGGL:
12905                 case RENDERPATH_D3D9:
12906                 case RENDERPATH_D3D10:
12907                 case RENDERPATH_D3D11:
12908                         RSurf_ActiveModelEntity(ent, true, true, false);
12909                         break;
12910                 case RENDERPATH_GL13:
12911                 case RENDERPATH_GL11:
12912                         RSurf_ActiveModelEntity(ent, true, false, false);
12913                         break;
12914                 }
12915         }
12916
12917         if (r_transparentdepthmasking.integer)
12918         {
12919                 qboolean setup = false;
12920                 for (i = 0;i < numsurfaces;i = j)
12921                 {
12922                         j = i + 1;
12923                         surface = rsurface.modelsurfaces + surfacelist[i];
12924                         texture = surface->texture;
12925                         rsurface.texture = R_GetCurrentTexture(texture);
12926                         rsurface.lightmaptexture = NULL;
12927                         rsurface.deluxemaptexture = NULL;
12928                         rsurface.uselightmaptexture = false;
12929                         // scan ahead until we find a different texture
12930                         endsurface = min(i + 1024, numsurfaces);
12931                         texturenumsurfaces = 0;
12932                         texturesurfacelist[texturenumsurfaces++] = surface;
12933                         for (;j < endsurface;j++)
12934                         {
12935                                 surface = rsurface.modelsurfaces + surfacelist[j];
12936                                 if (texture != surface->texture)
12937                                         break;
12938                                 texturesurfacelist[texturenumsurfaces++] = surface;
12939                         }
12940                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12941                                 continue;
12942                         // render the range of surfaces as depth
12943                         if (!setup)
12944                         {
12945                                 setup = true;
12946                                 GL_ColorMask(0,0,0,0);
12947                                 GL_Color(1,1,1,1);
12948                                 GL_DepthTest(true);
12949                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12950                                 GL_DepthMask(true);
12951                                 GL_AlphaTest(false);
12952                                 R_Mesh_ResetTextureState();
12953                                 R_SetupShader_DepthOrShadow();
12954                         }
12955                         RSurf_SetupDepthAndCulling();
12956                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12957                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12958                         RSurf_DrawBatch();
12959                 }
12960                 if (setup)
12961                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12962         }
12963
12964         for (i = 0;i < numsurfaces;i = j)
12965         {
12966                 j = i + 1;
12967                 surface = rsurface.modelsurfaces + surfacelist[i];
12968                 texture = surface->texture;
12969                 rsurface.texture = R_GetCurrentTexture(texture);
12970                 rsurface.lightmaptexture = surface->lightmaptexture;
12971                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12972                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12973                 // scan ahead until we find a different texture
12974                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12975                 texturenumsurfaces = 0;
12976                 texturesurfacelist[texturenumsurfaces++] = surface;
12977                 for (;j < endsurface;j++)
12978                 {
12979                         surface = rsurface.modelsurfaces + surfacelist[j];
12980                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12981                                 break;
12982                         texturesurfacelist[texturenumsurfaces++] = surface;
12983                 }
12984                 // render the range of surfaces
12985                 if (ent == r_refdef.scene.worldentity)
12986                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12987                 else
12988                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12989         }
12990         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12991         GL_AlphaTest(false);
12992 }
12993
12994 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12995 {
12996         // transparent surfaces get pushed off into the transparent queue
12997         int surfacelistindex;
12998         const msurface_t *surface;
12999         vec3_t tempcenter, center;
13000         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13001         {
13002                 surface = texturesurfacelist[surfacelistindex];
13003                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13004                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13005                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13006                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13007                 if (queueentity->transparent_offset) // transparent offset
13008                 {
13009                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13010                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13011                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13012                 }
13013                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13014         }
13015 }
13016
13017 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13018 {
13019         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13020                 return;
13021         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13022                 return;
13023         RSurf_SetupDepthAndCulling();
13024         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13025         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13026         RSurf_DrawBatch();
13027 }
13028
13029 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13030 {
13031         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13032         CHECKGLERROR
13033         if (depthonly)
13034                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13035         else if (prepass)
13036         {
13037                 if (!rsurface.texture->currentnumlayers)
13038                         return;
13039                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13040                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13041                 else
13042                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13043         }
13044         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13045                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13046         else if (!rsurface.texture->currentnumlayers)
13047                 return;
13048         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13049         {
13050                 // in the deferred case, transparent surfaces were queued during prepass
13051                 if (!r_shadow_usingdeferredprepass)
13052                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13053         }
13054         else
13055         {
13056                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13057                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13058         }
13059         CHECKGLERROR
13060 }
13061
13062 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13063 {
13064         int i, j;
13065         texture_t *texture;
13066         // break the surface list down into batches by texture and use of lightmapping
13067         for (i = 0;i < numsurfaces;i = j)
13068         {
13069                 j = i + 1;
13070                 // texture is the base texture pointer, rsurface.texture is the
13071                 // current frame/skin the texture is directing us to use (for example
13072                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13073                 // use skin 1 instead)
13074                 texture = surfacelist[i]->texture;
13075                 rsurface.texture = R_GetCurrentTexture(texture);
13076                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13077                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13078                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13079                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13080                 {
13081                         // if this texture is not the kind we want, skip ahead to the next one
13082                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13083                                 ;
13084                         continue;
13085                 }
13086                 // simply scan ahead until we find a different texture or lightmap state
13087                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13088                         ;
13089                 // render the range of surfaces
13090                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13091         }
13092 }
13093
13094 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13095 {
13096         CHECKGLERROR
13097         if (depthonly)
13098                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13099         else if (prepass)
13100         {
13101                 if (!rsurface.texture->currentnumlayers)
13102                         return;
13103                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13104                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13105                 else
13106                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13107         }
13108         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13109                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13110         else if (!rsurface.texture->currentnumlayers)
13111                 return;
13112         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13113         {
13114                 // in the deferred case, transparent surfaces were queued during prepass
13115                 if (!r_shadow_usingdeferredprepass)
13116                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13117         }
13118         else
13119         {
13120                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13121                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13122         }
13123         CHECKGLERROR
13124 }
13125
13126 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13127 {
13128         int i, j;
13129         texture_t *texture;
13130         // break the surface list down into batches by texture and use of lightmapping
13131         for (i = 0;i < numsurfaces;i = j)
13132         {
13133                 j = i + 1;
13134                 // texture is the base texture pointer, rsurface.texture is the
13135                 // current frame/skin the texture is directing us to use (for example
13136                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13137                 // use skin 1 instead)
13138                 texture = surfacelist[i]->texture;
13139                 rsurface.texture = R_GetCurrentTexture(texture);
13140                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13141                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13142                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13143                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13144                 {
13145                         // if this texture is not the kind we want, skip ahead to the next one
13146                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13147                                 ;
13148                         continue;
13149                 }
13150                 // simply scan ahead until we find a different texture or lightmap state
13151                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13152                         ;
13153                 // render the range of surfaces
13154                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13155         }
13156 }
13157
13158 float locboxvertex3f[6*4*3] =
13159 {
13160         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13161         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13162         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13163         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13164         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13165         1,0,0, 0,0,0, 0,1,0, 1,1,0
13166 };
13167
13168 unsigned short locboxelements[6*2*3] =
13169 {
13170          0, 1, 2, 0, 2, 3,
13171          4, 5, 6, 4, 6, 7,
13172          8, 9,10, 8,10,11,
13173         12,13,14, 12,14,15,
13174         16,17,18, 16,18,19,
13175         20,21,22, 20,22,23
13176 };
13177
13178 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13179 {
13180         int i, j;
13181         cl_locnode_t *loc = (cl_locnode_t *)ent;
13182         vec3_t mins, size;
13183         float vertex3f[6*4*3];
13184         CHECKGLERROR
13185         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13186         GL_DepthMask(false);
13187         GL_DepthRange(0, 1);
13188         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13189         GL_DepthTest(true);
13190         GL_CullFace(GL_NONE);
13191         R_EntityMatrix(&identitymatrix);
13192
13193         R_Mesh_ResetTextureState();
13194
13195         i = surfacelist[0];
13196         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13197                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13198                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13199                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13200
13201         if (VectorCompare(loc->mins, loc->maxs))
13202         {
13203                 VectorSet(size, 2, 2, 2);
13204                 VectorMA(loc->mins, -0.5f, size, mins);
13205         }
13206         else
13207         {
13208                 VectorCopy(loc->mins, mins);
13209                 VectorSubtract(loc->maxs, loc->mins, size);
13210         }
13211
13212         for (i = 0;i < 6*4*3;)
13213                 for (j = 0;j < 3;j++, i++)
13214                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13215
13216         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13217         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13218         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13219 }
13220
13221 void R_DrawLocs(void)
13222 {
13223         int index;
13224         cl_locnode_t *loc, *nearestloc;
13225         vec3_t center;
13226         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13227         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13228         {
13229                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13230                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13231         }
13232 }
13233
13234 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13235 {
13236         if (decalsystem->decals)
13237                 Mem_Free(decalsystem->decals);
13238         memset(decalsystem, 0, sizeof(*decalsystem));
13239 }
13240
13241 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)
13242 {
13243         tridecal_t *decal;
13244         tridecal_t *decals;
13245         int i;
13246
13247         // expand or initialize the system
13248         if (decalsystem->maxdecals <= decalsystem->numdecals)
13249         {
13250                 decalsystem_t old = *decalsystem;
13251                 qboolean useshortelements;
13252                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13253                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13254                 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)));
13255                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13256                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13257                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13258                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13259                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13260                 if (decalsystem->numdecals)
13261                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13262                 if (old.decals)
13263                         Mem_Free(old.decals);
13264                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13265                         decalsystem->element3i[i] = i;
13266                 if (useshortelements)
13267                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13268                                 decalsystem->element3s[i] = i;
13269         }
13270
13271         // grab a decal and search for another free slot for the next one
13272         decals = decalsystem->decals;
13273         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13274         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13275                 ;
13276         decalsystem->freedecal = i;
13277         if (decalsystem->numdecals <= i)
13278                 decalsystem->numdecals = i + 1;
13279
13280         // initialize the decal
13281         decal->lived = 0;
13282         decal->triangleindex = triangleindex;
13283         decal->surfaceindex = surfaceindex;
13284         decal->decalsequence = decalsequence;
13285         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13286         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13287         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13288         decal->color4ub[0][3] = 255;
13289         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13290         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13291         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13292         decal->color4ub[1][3] = 255;
13293         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13294         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13295         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13296         decal->color4ub[2][3] = 255;
13297         decal->vertex3f[0][0] = v0[0];
13298         decal->vertex3f[0][1] = v0[1];
13299         decal->vertex3f[0][2] = v0[2];
13300         decal->vertex3f[1][0] = v1[0];
13301         decal->vertex3f[1][1] = v1[1];
13302         decal->vertex3f[1][2] = v1[2];
13303         decal->vertex3f[2][0] = v2[0];
13304         decal->vertex3f[2][1] = v2[1];
13305         decal->vertex3f[2][2] = v2[2];
13306         decal->texcoord2f[0][0] = t0[0];
13307         decal->texcoord2f[0][1] = t0[1];
13308         decal->texcoord2f[1][0] = t1[0];
13309         decal->texcoord2f[1][1] = t1[1];
13310         decal->texcoord2f[2][0] = t2[0];
13311         decal->texcoord2f[2][1] = t2[1];
13312 }
13313
13314 extern cvar_t cl_decals_bias;
13315 extern cvar_t cl_decals_models;
13316 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13317 // baseparms, parms, temps
13318 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)
13319 {
13320         int cornerindex;
13321         int index;
13322         float v[9][3];
13323         const float *vertex3f;
13324         int numpoints;
13325         float points[2][9][3];
13326         float temp[3];
13327         float tc[9][2];
13328         float f;
13329         float c[9][4];
13330         const int *e;
13331
13332         e = rsurface.modelelement3i + 3*triangleindex;
13333
13334         vertex3f = rsurface.modelvertex3f;
13335
13336         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13337         {
13338                 index = 3*e[cornerindex];
13339                 VectorCopy(vertex3f + index, v[cornerindex]);
13340         }
13341         // cull backfaces
13342         //TriangleNormal(v[0], v[1], v[2], normal);
13343         //if (DotProduct(normal, localnormal) < 0.0f)
13344         //      continue;
13345         // clip by each of the box planes formed from the projection matrix
13346         // if anything survives, we emit the decal
13347         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]);
13348         if (numpoints < 3)
13349                 return;
13350         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]);
13351         if (numpoints < 3)
13352                 return;
13353         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]);
13354         if (numpoints < 3)
13355                 return;
13356         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]);
13357         if (numpoints < 3)
13358                 return;
13359         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]);
13360         if (numpoints < 3)
13361                 return;
13362         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]);
13363         if (numpoints < 3)
13364                 return;
13365         // some part of the triangle survived, so we have to accept it...
13366         if (dynamic)
13367         {
13368                 // dynamic always uses the original triangle
13369                 numpoints = 3;
13370                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13371                 {
13372                         index = 3*e[cornerindex];
13373                         VectorCopy(vertex3f + index, v[cornerindex]);
13374                 }
13375         }
13376         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13377         {
13378                 // convert vertex positions to texcoords
13379                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13380                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13381                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13382                 // calculate distance fade from the projection origin
13383                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13384                 f = bound(0.0f, f, 1.0f);
13385                 c[cornerindex][0] = r * f;
13386                 c[cornerindex][1] = g * f;
13387                 c[cornerindex][2] = b * f;
13388                 c[cornerindex][3] = 1.0f;
13389                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13390         }
13391         if (dynamic)
13392                 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);
13393         else
13394                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13395                         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);
13396 }
13397 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)
13398 {
13399         matrix4x4_t projection;
13400         decalsystem_t *decalsystem;
13401         qboolean dynamic;
13402         dp_model_t *model;
13403         const msurface_t *surface;
13404         const msurface_t *surfaces;
13405         const int *surfacelist;
13406         const texture_t *texture;
13407         int numtriangles;
13408         int numsurfacelist;
13409         int surfacelistindex;
13410         int surfaceindex;
13411         int triangleindex;
13412         float localorigin[3];
13413         float localnormal[3];
13414         float localmins[3];
13415         float localmaxs[3];
13416         float localsize;
13417         //float normal[3];
13418         float planes[6][4];
13419         float angles[3];
13420         bih_t *bih;
13421         int bih_triangles_count;
13422         int bih_triangles[256];
13423         int bih_surfaces[256];
13424
13425         decalsystem = &ent->decalsystem;
13426         model = ent->model;
13427         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13428         {
13429                 R_DecalSystem_Reset(&ent->decalsystem);
13430                 return;
13431         }
13432
13433         if (!model->brush.data_leafs && !cl_decals_models.integer)
13434         {
13435                 if (decalsystem->model)
13436                         R_DecalSystem_Reset(decalsystem);
13437                 return;
13438         }
13439
13440         if (decalsystem->model != model)
13441                 R_DecalSystem_Reset(decalsystem);
13442         decalsystem->model = model;
13443
13444         RSurf_ActiveModelEntity(ent, false, false, false);
13445
13446         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13447         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13448         VectorNormalize(localnormal);
13449         localsize = worldsize*rsurface.inversematrixscale;
13450         localmins[0] = localorigin[0] - localsize;
13451         localmins[1] = localorigin[1] - localsize;
13452         localmins[2] = localorigin[2] - localsize;
13453         localmaxs[0] = localorigin[0] + localsize;
13454         localmaxs[1] = localorigin[1] + localsize;
13455         localmaxs[2] = localorigin[2] + localsize;
13456
13457         //VectorCopy(localnormal, planes[4]);
13458         //VectorVectors(planes[4], planes[2], planes[0]);
13459         AnglesFromVectors(angles, localnormal, NULL, false);
13460         AngleVectors(angles, planes[0], planes[2], planes[4]);
13461         VectorNegate(planes[0], planes[1]);
13462         VectorNegate(planes[2], planes[3]);
13463         VectorNegate(planes[4], planes[5]);
13464         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13465         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13466         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13467         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13468         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13469         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13470
13471 #if 1
13472 // works
13473 {
13474         matrix4x4_t forwardprojection;
13475         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13476         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13477 }
13478 #else
13479 // broken
13480 {
13481         float projectionvector[4][3];
13482         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13483         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13484         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13485         projectionvector[0][0] = planes[0][0] * ilocalsize;
13486         projectionvector[0][1] = planes[1][0] * ilocalsize;
13487         projectionvector[0][2] = planes[2][0] * ilocalsize;
13488         projectionvector[1][0] = planes[0][1] * ilocalsize;
13489         projectionvector[1][1] = planes[1][1] * ilocalsize;
13490         projectionvector[1][2] = planes[2][1] * ilocalsize;
13491         projectionvector[2][0] = planes[0][2] * ilocalsize;
13492         projectionvector[2][1] = planes[1][2] * ilocalsize;
13493         projectionvector[2][2] = planes[2][2] * ilocalsize;
13494         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13495         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13496         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13497         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13498 }
13499 #endif
13500
13501         dynamic = model->surfmesh.isanimated;
13502         numsurfacelist = model->nummodelsurfaces;
13503         surfacelist = model->sortedmodelsurfaces;
13504         surfaces = model->data_surfaces;
13505
13506         bih = NULL;
13507         bih_triangles_count = -1;
13508         if(!dynamic)
13509         {
13510                 if(model->render_bih.numleafs)
13511                         bih = &model->render_bih;
13512                 else if(model->collision_bih.numleafs)
13513                         bih = &model->collision_bih;
13514         }
13515         if(bih)
13516                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13517         if(bih_triangles_count == 0)
13518                 return;
13519         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13520                 return;
13521         if(bih_triangles_count > 0)
13522         {
13523                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13524                 {
13525                         surfaceindex = bih_surfaces[triangleindex];
13526                         surface = surfaces + surfaceindex;
13527                         texture = surface->texture;
13528                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13529                                 continue;
13530                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13531                                 continue;
13532                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13533                 }
13534         }
13535         else
13536         {
13537                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13538                 {
13539                         surfaceindex = surfacelist[surfacelistindex];
13540                         surface = surfaces + surfaceindex;
13541                         // check cull box first because it rejects more than any other check
13542                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13543                                 continue;
13544                         // skip transparent surfaces
13545                         texture = surface->texture;
13546                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13547                                 continue;
13548                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13549                                 continue;
13550                         numtriangles = surface->num_triangles;
13551                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13552                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13553                 }
13554         }
13555 }
13556
13557 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13558 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)
13559 {
13560         int renderentityindex;
13561         float worldmins[3];
13562         float worldmaxs[3];
13563         entity_render_t *ent;
13564
13565         if (!cl_decals_newsystem.integer)
13566                 return;
13567
13568         worldmins[0] = worldorigin[0] - worldsize;
13569         worldmins[1] = worldorigin[1] - worldsize;
13570         worldmins[2] = worldorigin[2] - worldsize;
13571         worldmaxs[0] = worldorigin[0] + worldsize;
13572         worldmaxs[1] = worldorigin[1] + worldsize;
13573         worldmaxs[2] = worldorigin[2] + worldsize;
13574
13575         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13576
13577         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13578         {
13579                 ent = r_refdef.scene.entities[renderentityindex];
13580                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13581                         continue;
13582
13583                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13584         }
13585 }
13586
13587 typedef struct r_decalsystem_splatqueue_s
13588 {
13589         vec3_t worldorigin;
13590         vec3_t worldnormal;
13591         float color[4];
13592         float tcrange[4];
13593         float worldsize;
13594         int decalsequence;
13595 }
13596 r_decalsystem_splatqueue_t;
13597
13598 int r_decalsystem_numqueued = 0;
13599 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13600
13601 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)
13602 {
13603         r_decalsystem_splatqueue_t *queue;
13604
13605         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13606                 return;
13607
13608         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13609         VectorCopy(worldorigin, queue->worldorigin);
13610         VectorCopy(worldnormal, queue->worldnormal);
13611         Vector4Set(queue->color, r, g, b, a);
13612         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13613         queue->worldsize = worldsize;
13614         queue->decalsequence = cl.decalsequence++;
13615 }
13616
13617 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13618 {
13619         int i;
13620         r_decalsystem_splatqueue_t *queue;
13621
13622         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13623                 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);
13624         r_decalsystem_numqueued = 0;
13625 }
13626
13627 extern cvar_t cl_decals_max;
13628 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13629 {
13630         int i;
13631         decalsystem_t *decalsystem = &ent->decalsystem;
13632         int numdecals;
13633         int killsequence;
13634         tridecal_t *decal;
13635         float frametime;
13636         float lifetime;
13637
13638         if (!decalsystem->numdecals)
13639                 return;
13640
13641         if (r_showsurfaces.integer)
13642                 return;
13643
13644         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13645         {
13646                 R_DecalSystem_Reset(decalsystem);
13647                 return;
13648         }
13649
13650         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13651         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13652
13653         if (decalsystem->lastupdatetime)
13654                 frametime = (cl.time - decalsystem->lastupdatetime);
13655         else
13656                 frametime = 0;
13657         decalsystem->lastupdatetime = cl.time;
13658         decal = decalsystem->decals;
13659         numdecals = decalsystem->numdecals;
13660
13661         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13662         {
13663                 if (decal->color4ub[0][3])
13664                 {
13665                         decal->lived += frametime;
13666                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13667                         {
13668                                 memset(decal, 0, sizeof(*decal));
13669                                 if (decalsystem->freedecal > i)
13670                                         decalsystem->freedecal = i;
13671                         }
13672                 }
13673         }
13674         decal = decalsystem->decals;
13675         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13676                 numdecals--;
13677
13678         // collapse the array by shuffling the tail decals into the gaps
13679         for (;;)
13680         {
13681                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13682                         decalsystem->freedecal++;
13683                 if (decalsystem->freedecal == numdecals)
13684                         break;
13685                 decal[decalsystem->freedecal] = decal[--numdecals];
13686         }
13687
13688         decalsystem->numdecals = numdecals;
13689
13690         if (numdecals <= 0)
13691         {
13692                 // if there are no decals left, reset decalsystem
13693                 R_DecalSystem_Reset(decalsystem);
13694         }
13695 }
13696
13697 extern skinframe_t *decalskinframe;
13698 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13699 {
13700         int i;
13701         decalsystem_t *decalsystem = &ent->decalsystem;
13702         int numdecals;
13703         tridecal_t *decal;
13704         float faderate;
13705         float alpha;
13706         float *v3f;
13707         float *c4f;
13708         float *t2f;
13709         const int *e;
13710         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13711         int numtris = 0;
13712
13713         numdecals = decalsystem->numdecals;
13714         if (!numdecals)
13715                 return;
13716
13717         if (r_showsurfaces.integer)
13718                 return;
13719
13720         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13721         {
13722                 R_DecalSystem_Reset(decalsystem);
13723                 return;
13724         }
13725
13726         // if the model is static it doesn't matter what value we give for
13727         // wantnormals and wanttangents, so this logic uses only rules applicable
13728         // to a model, knowing that they are meaningless otherwise
13729         if (ent == r_refdef.scene.worldentity)
13730                 RSurf_ActiveWorldEntity();
13731         else
13732                 RSurf_ActiveModelEntity(ent, false, false, false);
13733
13734         decalsystem->lastupdatetime = cl.time;
13735         decal = decalsystem->decals;
13736
13737         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13738
13739         // update vertex positions for animated models
13740         v3f = decalsystem->vertex3f;
13741         c4f = decalsystem->color4f;
13742         t2f = decalsystem->texcoord2f;
13743         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13744         {
13745                 if (!decal->color4ub[0][3])
13746                         continue;
13747
13748                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13749                         continue;
13750
13751                 // update color values for fading decals
13752                 if (decal->lived >= cl_decals_time.value)
13753                 {
13754                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13755                         alpha *= (1.0f/255.0f);
13756                 }
13757                 else
13758                         alpha = 1.0f/255.0f;
13759
13760                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13761                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13762                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13763                 c4f[ 3] = 1;
13764                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13765                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13766                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13767                 c4f[ 7] = 1;
13768                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13769                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13770                 c4f[10] = decal->color4ub[2][2] * alpha;
13771                 c4f[11] = 1;
13772
13773                 t2f[0] = decal->texcoord2f[0][0];
13774                 t2f[1] = decal->texcoord2f[0][1];
13775                 t2f[2] = decal->texcoord2f[1][0];
13776                 t2f[3] = decal->texcoord2f[1][1];
13777                 t2f[4] = decal->texcoord2f[2][0];
13778                 t2f[5] = decal->texcoord2f[2][1];
13779
13780                 // update vertex positions for animated models
13781                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13782                 {
13783                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13784                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13785                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13786                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13787                 }
13788                 else
13789                 {
13790                         VectorCopy(decal->vertex3f[0], v3f);
13791                         VectorCopy(decal->vertex3f[1], v3f + 3);
13792                         VectorCopy(decal->vertex3f[2], v3f + 6);
13793                 }
13794
13795                 if (r_refdef.fogenabled)
13796                 {
13797                         alpha = RSurf_FogVertex(v3f);
13798                         VectorScale(c4f, alpha, c4f);
13799                         alpha = RSurf_FogVertex(v3f + 3);
13800                         VectorScale(c4f + 4, alpha, c4f + 4);
13801                         alpha = RSurf_FogVertex(v3f + 6);
13802                         VectorScale(c4f + 8, alpha, c4f + 8);
13803                 }
13804
13805                 v3f += 9;
13806                 c4f += 12;
13807                 t2f += 6;
13808                 numtris++;
13809         }
13810
13811         if (numtris > 0)
13812         {
13813                 r_refdef.stats.drawndecals += numtris;
13814
13815                 // now render the decals all at once
13816                 // (this assumes they all use one particle font texture!)
13817                 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);
13818                 R_Mesh_ResetTextureState();
13819                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13820                 GL_DepthMask(false);
13821                 GL_DepthRange(0, 1);
13822                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13823                 GL_DepthTest(true);
13824                 GL_CullFace(GL_NONE);
13825                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13826                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13827                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13828         }
13829 }
13830
13831 static void R_DrawModelDecals(void)
13832 {
13833         int i, numdecals;
13834
13835         // fade faster when there are too many decals
13836         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13837         for (i = 0;i < r_refdef.scene.numentities;i++)
13838                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13839
13840         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13841         for (i = 0;i < r_refdef.scene.numentities;i++)
13842                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13843                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13844
13845         R_DecalSystem_ApplySplatEntitiesQueue();
13846
13847         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13848         for (i = 0;i < r_refdef.scene.numentities;i++)
13849                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13850
13851         r_refdef.stats.totaldecals += numdecals;
13852
13853         if (r_showsurfaces.integer)
13854                 return;
13855
13856         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13857
13858         for (i = 0;i < r_refdef.scene.numentities;i++)
13859         {
13860                 if (!r_refdef.viewcache.entityvisible[i])
13861                         continue;
13862                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13863                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13864         }
13865 }
13866
13867 extern cvar_t mod_collision_bih;
13868 void R_DrawDebugModel(void)
13869 {
13870         entity_render_t *ent = rsurface.entity;
13871         int i, j, k, l, flagsmask;
13872         const msurface_t *surface;
13873         dp_model_t *model = ent->model;
13874         vec3_t v;
13875
13876         switch(vid.renderpath)
13877         {
13878         case RENDERPATH_GL11:
13879         case RENDERPATH_GL13:
13880         case RENDERPATH_GL20:
13881         case RENDERPATH_CGGL:
13882                 break;
13883         case RENDERPATH_D3D9:
13884                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13885                 return;
13886         case RENDERPATH_D3D10:
13887                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13888                 return;
13889         case RENDERPATH_D3D11:
13890                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13891                 return;
13892         }
13893
13894         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13895
13896         R_Mesh_ResetTextureState();
13897         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13898         GL_DepthRange(0, 1);
13899         GL_DepthTest(!r_showdisabledepthtest.integer);
13900         GL_DepthMask(false);
13901         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13902
13903         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13904         {
13905                 int triangleindex;
13906                 int bihleafindex;
13907                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13908                 const q3mbrush_t *brush;
13909                 const bih_t *bih = &model->collision_bih;
13910                 const bih_leaf_t *bihleaf;
13911                 float vertex3f[3][3];
13912                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13913                 cullbox = false;
13914                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13915                 {
13916                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13917                                 continue;
13918                         switch (bihleaf->type)
13919                         {
13920                         case BIH_BRUSH:
13921                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13922                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13923                                 {
13924                                         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);
13925                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13926                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13927                                 }
13928                                 break;
13929                         case BIH_COLLISIONTRIANGLE:
13930                                 triangleindex = bihleaf->itemindex;
13931                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13932                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13933                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13934                                 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);
13935                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13936                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13937                                 break;
13938                         case BIH_RENDERTRIANGLE:
13939                                 triangleindex = bihleaf->itemindex;
13940                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13941                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13942                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13943                                 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);
13944                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13945                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13946                                 break;
13947                         }
13948                 }
13949         }
13950
13951         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13952
13953         if (r_showtris.integer || r_shownormals.integer)
13954         {
13955                 if (r_showdisabledepthtest.integer)
13956                 {
13957                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13958                         GL_DepthMask(false);
13959                 }
13960                 else
13961                 {
13962                         GL_BlendFunc(GL_ONE, GL_ZERO);
13963                         GL_DepthMask(true);
13964                 }
13965                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13966                 {
13967                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13968                                 continue;
13969                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13970                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13971                         {
13972                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13973                                 if (r_showtris.value > 0)
13974                                 {
13975                                         if (!rsurface.texture->currentlayers->depthmask)
13976                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13977                                         else if (ent == r_refdef.scene.worldentity)
13978                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13979                                         else
13980                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13981                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13982                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13983                                         RSurf_DrawBatch();
13984                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13985                                         CHECKGLERROR
13986                                 }
13987                                 if (r_shownormals.value < 0)
13988                                 {
13989                                         qglBegin(GL_LINES);
13990                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13991                                         {
13992                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13993                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13994                                                 qglVertex3f(v[0], v[1], v[2]);
13995                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13996                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13997                                                 qglVertex3f(v[0], v[1], v[2]);
13998                                         }
13999                                         qglEnd();
14000                                         CHECKGLERROR
14001                                 }
14002                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14003                                 {
14004                                         qglBegin(GL_LINES);
14005                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14006                                         {
14007                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14008                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14009                                                 qglVertex3f(v[0], v[1], v[2]);
14010                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14011                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14012                                                 qglVertex3f(v[0], v[1], v[2]);
14013                                         }
14014                                         qglEnd();
14015                                         CHECKGLERROR
14016                                         qglBegin(GL_LINES);
14017                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14018                                         {
14019                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14020                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14021                                                 qglVertex3f(v[0], v[1], v[2]);
14022                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14023                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14024                                                 qglVertex3f(v[0], v[1], v[2]);
14025                                         }
14026                                         qglEnd();
14027                                         CHECKGLERROR
14028                                         qglBegin(GL_LINES);
14029                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14030                                         {
14031                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14032                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14033                                                 qglVertex3f(v[0], v[1], v[2]);
14034                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14035                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14036                                                 qglVertex3f(v[0], v[1], v[2]);
14037                                         }
14038                                         qglEnd();
14039                                         CHECKGLERROR
14040                                 }
14041                         }
14042                 }
14043                 rsurface.texture = NULL;
14044         }
14045 }
14046
14047 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14048 int r_maxsurfacelist = 0;
14049 const msurface_t **r_surfacelist = NULL;
14050 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14051 {
14052         int i, j, endj, flagsmask;
14053         dp_model_t *model = r_refdef.scene.worldmodel;
14054         msurface_t *surfaces;
14055         unsigned char *update;
14056         int numsurfacelist = 0;
14057         if (model == NULL)
14058                 return;
14059
14060         if (r_maxsurfacelist < model->num_surfaces)
14061         {
14062                 r_maxsurfacelist = model->num_surfaces;
14063                 if (r_surfacelist)
14064                         Mem_Free((msurface_t**)r_surfacelist);
14065                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14066         }
14067
14068         RSurf_ActiveWorldEntity();
14069
14070         surfaces = model->data_surfaces;
14071         update = model->brushq1.lightmapupdateflags;
14072
14073         // update light styles on this submodel
14074         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14075         {
14076                 model_brush_lightstyleinfo_t *style;
14077                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14078                 {
14079                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14080                         {
14081                                 int *list = style->surfacelist;
14082                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14083                                 for (j = 0;j < style->numsurfaces;j++)
14084                                         update[list[j]] = true;
14085                         }
14086                 }
14087         }
14088
14089         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14090
14091         if (debug)
14092         {
14093                 R_DrawDebugModel();
14094                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14095                 return;
14096         }
14097
14098         rsurface.lightmaptexture = NULL;
14099         rsurface.deluxemaptexture = NULL;
14100         rsurface.uselightmaptexture = false;
14101         rsurface.texture = NULL;
14102         rsurface.rtlight = NULL;
14103         numsurfacelist = 0;
14104         // add visible surfaces to draw list
14105         for (i = 0;i < model->nummodelsurfaces;i++)
14106         {
14107                 j = model->sortedmodelsurfaces[i];
14108                 if (r_refdef.viewcache.world_surfacevisible[j])
14109                         r_surfacelist[numsurfacelist++] = surfaces + j;
14110         }
14111         // update lightmaps if needed
14112         if (model->brushq1.firstrender)
14113         {
14114                 model->brushq1.firstrender = false;
14115                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14116                         if (update[j])
14117                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14118         }
14119         else if (update)
14120         {
14121                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14122                         if (r_refdef.viewcache.world_surfacevisible[j])
14123                                 if (update[j])
14124                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14125         }
14126         // don't do anything if there were no surfaces
14127         if (!numsurfacelist)
14128         {
14129                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14130                 return;
14131         }
14132         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14133         GL_AlphaTest(false);
14134
14135         // add to stats if desired
14136         if (r_speeds.integer && !skysurfaces && !depthonly)
14137         {
14138                 r_refdef.stats.world_surfaces += numsurfacelist;
14139                 for (j = 0;j < numsurfacelist;j++)
14140                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14141         }
14142
14143         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14144 }
14145
14146 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14147 {
14148         int i, j, endj, flagsmask;
14149         dp_model_t *model = ent->model;
14150         msurface_t *surfaces;
14151         unsigned char *update;
14152         int numsurfacelist = 0;
14153         if (model == NULL)
14154                 return;
14155
14156         if (r_maxsurfacelist < model->num_surfaces)
14157         {
14158                 r_maxsurfacelist = model->num_surfaces;
14159                 if (r_surfacelist)
14160                         Mem_Free((msurface_t **)r_surfacelist);
14161                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14162         }
14163
14164         // if the model is static it doesn't matter what value we give for
14165         // wantnormals and wanttangents, so this logic uses only rules applicable
14166         // to a model, knowing that they are meaningless otherwise
14167         if (ent == r_refdef.scene.worldentity)
14168                 RSurf_ActiveWorldEntity();
14169         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14170                 RSurf_ActiveModelEntity(ent, false, false, false);
14171         else if (prepass)
14172                 RSurf_ActiveModelEntity(ent, true, true, true);
14173         else if (depthonly)
14174         {
14175                 switch (vid.renderpath)
14176                 {
14177                 case RENDERPATH_GL20:
14178                 case RENDERPATH_CGGL:
14179                 case RENDERPATH_D3D9:
14180                 case RENDERPATH_D3D10:
14181                 case RENDERPATH_D3D11:
14182                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14183                         break;
14184                 case RENDERPATH_GL13:
14185                 case RENDERPATH_GL11:
14186                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14187                         break;
14188                 }
14189         }
14190         else
14191         {
14192                 switch (vid.renderpath)
14193                 {
14194                 case RENDERPATH_GL20:
14195                 case RENDERPATH_CGGL:
14196                 case RENDERPATH_D3D9:
14197                 case RENDERPATH_D3D10:
14198                 case RENDERPATH_D3D11:
14199                         RSurf_ActiveModelEntity(ent, true, true, false);
14200                         break;
14201                 case RENDERPATH_GL13:
14202                 case RENDERPATH_GL11:
14203                         RSurf_ActiveModelEntity(ent, true, false, false);
14204                         break;
14205                 }
14206         }
14207
14208         surfaces = model->data_surfaces;
14209         update = model->brushq1.lightmapupdateflags;
14210
14211         // update light styles
14212         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14213         {
14214                 model_brush_lightstyleinfo_t *style;
14215                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14216                 {
14217                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14218                         {
14219                                 int *list = style->surfacelist;
14220                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14221                                 for (j = 0;j < style->numsurfaces;j++)
14222                                         update[list[j]] = true;
14223                         }
14224                 }
14225         }
14226
14227         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14228
14229         if (debug)
14230         {
14231                 R_DrawDebugModel();
14232                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14233                 return;
14234         }
14235
14236         rsurface.lightmaptexture = NULL;
14237         rsurface.deluxemaptexture = NULL;
14238         rsurface.uselightmaptexture = false;
14239         rsurface.texture = NULL;
14240         rsurface.rtlight = NULL;
14241         numsurfacelist = 0;
14242         // add visible surfaces to draw list
14243         for (i = 0;i < model->nummodelsurfaces;i++)
14244                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14245         // don't do anything if there were no surfaces
14246         if (!numsurfacelist)
14247         {
14248                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14249                 return;
14250         }
14251         // update lightmaps if needed
14252         if (update)
14253         {
14254                 int updated = 0;
14255                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14256                 {
14257                         if (update[j])
14258                         {
14259                                 updated++;
14260                                 R_BuildLightMap(ent, surfaces + j);
14261                         }
14262                 }
14263         }
14264         if (update)
14265                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14266                         if (update[j])
14267                                 R_BuildLightMap(ent, surfaces + j);
14268         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14269         GL_AlphaTest(false);
14270
14271         // add to stats if desired
14272         if (r_speeds.integer && !skysurfaces && !depthonly)
14273         {
14274                 r_refdef.stats.entities_surfaces += numsurfacelist;
14275                 for (j = 0;j < numsurfacelist;j++)
14276                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14277         }
14278
14279         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14280 }
14281
14282 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14283 {
14284         static texture_t texture;
14285         static msurface_t surface;
14286         const msurface_t *surfacelist = &surface;
14287
14288         // fake enough texture and surface state to render this geometry
14289
14290         texture.update_lastrenderframe = -1; // regenerate this texture
14291         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14292         texture.currentskinframe = skinframe;
14293         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14294         texture.offsetmapping = OFFSETMAPPING_OFF;
14295         texture.offsetscale = 1;
14296         texture.specularscalemod = 1;
14297         texture.specularpowermod = 1;
14298
14299         surface.texture = &texture;
14300         surface.num_triangles = numtriangles;
14301         surface.num_firsttriangle = firsttriangle;
14302         surface.num_vertices = numvertices;
14303         surface.num_firstvertex = firstvertex;
14304
14305         // now render it
14306         rsurface.texture = R_GetCurrentTexture(surface.texture);
14307         rsurface.lightmaptexture = NULL;
14308         rsurface.deluxemaptexture = NULL;
14309         rsurface.uselightmaptexture = false;
14310         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14311 }
14312
14313 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)
14314 {
14315         static msurface_t surface;
14316         const msurface_t *surfacelist = &surface;
14317
14318         // fake enough texture and surface state to render this geometry
14319
14320         surface.texture = texture;
14321         surface.num_triangles = numtriangles;
14322         surface.num_firsttriangle = firsttriangle;
14323         surface.num_vertices = numvertices;
14324         surface.num_firstvertex = firstvertex;
14325
14326         // now render it
14327         rsurface.texture = R_GetCurrentTexture(surface.texture);
14328         rsurface.lightmaptexture = NULL;
14329         rsurface.deluxemaptexture = NULL;
14330         rsurface.uselightmaptexture = false;
14331         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14332 }