]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a crash in D3D9 with r_sky 0
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
146
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
170
171 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
172
173 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
502         }
503 }
504
505 static void R_BuildFogHeightTexture(void)
506 {
507         unsigned char *inpixels;
508         int size;
509         int x;
510         int y;
511         int j;
512         float c[4];
513         float f;
514         inpixels = NULL;
515         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516         if (r_refdef.fogheighttexturename[0])
517                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
518         if (!inpixels)
519         {
520                 r_refdef.fog_height_tablesize = 0;
521                 if (r_texture_fogheighttexture)
522                         R_FreeTexture(r_texture_fogheighttexture);
523                 r_texture_fogheighttexture = NULL;
524                 if (r_refdef.fog_height_table2d)
525                         Mem_Free(r_refdef.fog_height_table2d);
526                 r_refdef.fog_height_table2d = NULL;
527                 if (r_refdef.fog_height_table1d)
528                         Mem_Free(r_refdef.fog_height_table1d);
529                 r_refdef.fog_height_table1d = NULL;
530                 return;
531         }
532         size = image_width;
533         r_refdef.fog_height_tablesize = size;
534         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
537         Mem_Free(inpixels);
538         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
539         // average fog color table accounting for every fog layer between a point
540         // and the camera.  (Note: attenuation is handled separately!)
541         for (y = 0;y < size;y++)
542         {
543                 for (x = 0;x < size;x++)
544                 {
545                         Vector4Clear(c);
546                         f = 0;
547                         if (x < y)
548                         {
549                                 for (j = x;j <= y;j++)
550                                 {
551                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
552                                         f++;
553                                 }
554                         }
555                         else
556                         {
557                                 for (j = x;j >= y;j--)
558                                 {
559                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
560                                         f++;
561                                 }
562                         }
563                         f = 1.0f / f;
564                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
568                 }
569         }
570         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
571 }
572
573 //=======================================================================================================================================================
574
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "#   extension GL_EXT_gpu_shader4 : enable\n"
593 "# endif\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "#   extension GL_ARB_texture_gather : enable\n"
596 "# else\n"
597 "#   ifdef GL_AMD_texture_texture4\n"
598 "#     extension GL_AMD_texture_texture4 : enable\n"
599 "#   endif\n"
600 "# endif\n"
601 "#endif\n"
602 "\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
605 "//#endif\n"
606 "\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
612 "//#else\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
617 "//#endif\n"
618 "\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
621 "#endif\n"
622 "\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
625 "void main(void)\n"
626 "{\n"
627 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
628 "}\n"
629 "#endif\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
631 "\n"
632 "\n"
633 "\n"
634 "\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
641 "}\n"
642 "#endif\n"
643 "\n"
644 "#ifdef FRAGMENT_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_FragColor = gl_Color;\n"
648 "}\n"
649 "#endif\n"
650 "#else // !MODE_SHOWDEPTH\n"
651 "\n"
652 "\n"
653 "\n"
654 "\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
658 "\n"
659 "#ifdef VERTEX_SHADER\n"
660 "void main(void)\n"
661 "{\n"
662 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USEBLOOM\n"
665 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
666 "#endif\n"
667 "}\n"
668 "#endif\n"
669 "\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
672 "#ifdef USEBLOOM\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
675 "#endif\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
678 "#endif\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
681 "#endif\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
684 "#endif\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
695 "#ifdef USEBLOOM\n"
696 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
697 "#endif\n"
698 "#ifdef USEVIEWTINT\n"
699 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
700 "#endif\n"
701 "\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
705 "       float sobel = 1.0;\n"
706 "       // vec2 ts = textureSize(Texture_First, 0);\n"
707 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 "       vec2 px = PixelSize;\n"
709 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
711 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
714 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
717 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
720 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
738 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
739 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USESATURATION\n"
744 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USEGAMMARAMPS\n"
751 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
754 "#endif\n"
755 "}\n"
756 "#endif\n"
757 "#else // !MODE_POSTPROCESS\n"
758 "\n"
759 "\n"
760 "\n"
761 "\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
765 "#endif\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
768 "#endif\n"
769 "#ifdef VERTEX_SHADER\n"
770 "void main(void)\n"
771 "{\n"
772 "       gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
775 "#endif\n"
776 "#ifdef USESPECULAR\n"
777 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
778 "#endif\n"
779 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
780 "}\n"
781 "#endif\n"
782 "\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
789 "#endif\n"
790 "\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
796 "#endif\n"
797 "\n"
798 "#ifdef USESPECULAR\n"
799 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 "       gl_FragColor *= tex2;\n"
802 "# endif\n"
803 "# ifdef USEGLOW\n"
804 "       gl_FragColor += tex2;\n"
805 "# endif\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
808 "# endif\n"
809 "#endif\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_GENERIC\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
820 "void main(void)\n"
821 "{\n"
822 "       gl_FrontColor = gl_Color;\n"
823 "       TexCoord = gl_MultiTexCoord0.xy;\n"
824 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
825 "}\n"
826 "#endif\n"
827 "\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
831 "\n"
832 "void main(void)\n"
833 "{\n"
834 "       int i;\n"
835 "       vec2 tc = TexCoord;\n"
836 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 "       tc += BloomBlur_Parameters.xy;\n"
838 "       for (i = 1;i < SAMPLES;i++)\n"
839 "       {\n"
840 "               color += texture2D(Texture_First, tc).rgb;\n"
841 "               tc += BloomBlur_Parameters.xy;\n"
842 "       }\n"
843 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
852 "\n"
853 "void main(void)\n"
854 "{\n"
855 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 "       ModelViewProjectionPosition = gl_Position;\n"
858 "}\n"
859 "#endif\n"
860 "\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
865 "\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
873 "\n"
874 "void main(void)\n"
875 "{\n"
876 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 "       // FIXME temporary hack to detect the case that the reflection\n"
881 "       // gets blackened at edges due to leaving the area that contains actual\n"
882 "       // content.\n"
883 "       // Remove this 'ack once we have a better way to stop this thing from\n"
884 "       // 'appening.\n"
885 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
891 "}\n"
892 "#endif\n"
893 "#else // !MODE_REFRACTION\n"
894 "\n"
895 "\n"
896 "\n"
897 "\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
905 "\n"
906 "void main(void)\n"
907 "{\n"
908 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 "       // FIXME temporary hack to detect the case that the reflection\n"
939 "       // gets blackened at edges due to leaving the area that contains actual\n"
940 "       // content.\n"
941 "       // Remove this 'ack once we have a better way to stop this thing from\n"
942 "       // 'appening.\n"
943 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
955 "}\n"
956 "#endif\n"
957 "#else // !MODE_WATER\n"
958 "\n"
959 "\n"
960 "\n"
961 "\n"
962 "// common definitions between vertex shader and fragment shader:\n"
963 "\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
967 "#endif\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
970 "#endif\n"
971 "\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
974 "#endif\n"
975 "\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
982 "#endif\n"
983 "#ifdef USEFOG\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
985 "#endif\n"
986 "\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
991 "#endif\n"
992 "\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
995 "#endif\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1003 "#endif\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1007 "#endif\n"
1008 "uniform vec4 FogPlane;\n"
1009 "\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1012 "#endif\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "\n"
1018 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1019 "\n"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1022 "\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1026 "#ifdef USEGLOW\n"
1027 "uniform sampler2D Texture_Glow;\n"
1028 "#endif\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1033 "#ifdef USEGLOW\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1035 "#endif\n"
1036 "#endif\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1040 "#endif\n"
1041 "#ifdef USEFOG\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1044 "#endif\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1046 "#endif\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1049 "#endif\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1052 "#endif\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1055 "#endif\n"
1056 "\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1060 "#endif\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1064 "#endif\n"
1065 "\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1069 "\n"
1070 "#ifdef USEFOG\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1075 "{\n"
1076 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1078 "       float fogfrac;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 "       fogfrac = fogheightpixel.a;\n"
1082 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1083 "#else\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1086 "# else\n"
1087 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1088 "# endif\n"
1089 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1090 "#endif\n"
1091 "}\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1097 "{\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 "       // 14 sample relief mapping: linear search and then binary search\n"
1100 "       // this basically steps forward a small amount repeatedly until it finds\n"
1101 "       // itself inside solid, then jitters forward and back using decreasing\n"
1102 "       // amounts to find the impact\n"
1103 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 "       vec3 RT = vec3(TexCoord, 1);\n"
1107 "       OffsetVector *= 0.1;\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1118 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1119 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1120 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1121 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1122 "       return RT.xy;\n"
1123 "#else\n"
1124 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 "       // this basically moves forward the full distance, and then backs up based\n"
1126 "       // on height of samples\n"
1127 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 "       TexCoord += OffsetVector;\n"
1131 "       OffsetVector *= 0.333;\n"
1132 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 "       return TexCoord;\n"
1136 "#endif\n"
1137 "}\n"
1138 "#endif // USEOFFSETMAPPING\n"
1139 "\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1143 "#endif\n"
1144 "\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1146 "\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1150 "# else\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1152 "# endif\n"
1153 "#endif\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1157 "#endif\n"
1158 "\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1162 "#endif\n"
1163 "\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1167 "# else\n"
1168 "#  ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1175 "}\n"
1176 "#  else\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 adir = abs(dir);\n"
1180 "       float ma = adir.z;\n"
1181 "       vec4 proj = vec4(dir, 2.5);\n"
1182 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1186 "}\n"
1187 "#  endif\n"
1188 "# endif\n"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1190 "\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1193 "{\n"
1194 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1195 "       float f;\n"
1196 "\n"
1197 "#  ifdef USESHADOWSAMPLER\n"
1198 "#    ifdef USESHADOWMAPPCF\n"
1199 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1200 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1202 "#    else\n"
1203 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1204 "#    endif\n"
1205 "#  else\n"
1206 "#    ifdef USESHADOWMAPPCF\n"
1207 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "#      ifdef GL_ARB_texture_gather\n"
1209 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1210 "#      else\n"
1211 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1212 "#      endif\n"
1213 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "#      if USESHADOWMAPPCF > 1\n"
1215 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1219 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1220 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1221 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1222 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1223 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1224 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 "       locols.yz += group2.ab;\n"
1227 "       hicols.yz += group8.rg;\n"
1228 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 "                               mix(locols, hicols, offset.y);\n"
1231 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 "       f = dot(cols, vec4(1.0/25.0));\n"
1234 "#      else\n"
1235 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1238 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1239 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1242 "#      endif\n"
1243 "#     else\n"
1244 "#      ifdef GL_EXT_gpu_shader4\n"
1245 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1248 "#      endif\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 "       center *= ShadowMap_TextureScale;\n"
1252 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1253 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1254 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1255 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1256 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1258 "#      else\n"
1259 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1262 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1263 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1265 "#      endif\n"
1266 "#     endif\n"
1267 "#    else\n"
1268 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1269 "#    endif\n"
1270 "#  endif\n"
1271 "#  ifdef USESHADOWMAPORTHO\n"
1272 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1273 "#  else\n"
1274 "       return f;\n"
1275 "#  endif\n"
1276 "}\n"
1277 "# endif\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1280 "\n"
1281 "\n"
1282 "\n"
1283 "\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1289 "#endif\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1291 "void main(void)\n"
1292 "{\n"
1293 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 "       gl_FrontColor = gl_Color;\n"
1296 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1297 "#endif\n"
1298 "\n"
1299 "       // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1305 "#endif\n"
1306 "\n"
1307 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1311 "}\n"
1312 "#endif // VERTEX_SHADER\n"
1313 "\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1315 "void main(void)\n"
1316 "{\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 "       // apply offsetmapping\n"
1319 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1321 "#endif\n"
1322 "\n"
1323 "#ifdef USEALPHAKILL\n"
1324 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "               discard;\n"
1326 "#endif\n"
1327 "\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1333 "#endif\n"
1334 "\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1338 "#else\n"
1339 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1341 "#endif\n"
1342 "\n"
1343 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1344 "}\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1347 "\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1354 "void main(void)\n"
1355 "{\n"
1356 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1358 "}\n"
1359 "#endif // VERTEX_SHADER\n"
1360 "\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1370 "#endif\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       // calculate viewspace pixel position\n"
1375 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1376 "       vec3 position;\n"
1377 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 "       // decode viewspace pixel normal\n"
1380 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 "       // surfacenormal = pixel normal in viewspace\n"
1383 "       // LightVector = pixel to light in viewspace\n"
1384 "       // CubeVector = position in lightspace\n"
1385 "       // eyevector = pixel to view in viewspace\n"
1386 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 "       // calculate diffuse shading\n"
1390 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1392 "#endif\n"
1393 "#ifdef USESPECULAR\n"
1394 "       // calculate directional shading\n"
1395 "       vec3 eyevector = position * -1.0;\n"
1396 "#  ifdef USEEXACTSPECULARMATH\n"
1397 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1398 "#  else\n"
1399 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1401 "#  endif\n"
1402 "#endif\n"
1403 "\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 "       fade *= ShadowMapCompare(CubeVector);\n"
1406 "#endif\n"
1407 "\n"
1408 "#ifdef USEDIFFUSE\n"
1409 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1410 "#else\n"
1411 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1412 "#endif\n"
1413 "#ifdef USESPECULAR\n"
1414 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1415 "#else\n"
1416 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1417 "#endif\n"
1418 "\n"
1419 "# ifdef USECUBEFILTER\n"
1420 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 "       gl_FragData[0].rgb *= cubecolor;\n"
1422 "       gl_FragData[1].rgb *= cubecolor;\n"
1423 "# endif\n"
1424 "}\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1427 "\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1435 "#endif\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1438 "#endif\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1441 "#endif\n"
1442 "void main(void)\n"
1443 "{\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 "       gl_FrontColor = gl_Color;\n"
1446 "#endif\n"
1447 "       // copy the surface texcoord\n"
1448 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1451 "#endif\n"
1452 "#ifdef USELIGHTMAP\n"
1453 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "       // transform vertex position into light attenuation/cubemap space\n"
1458 "       // (-1 to +1 across the light box)\n"
1459 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1460 "\n"
1461 "# ifdef USEDIFFUSE\n"
1462 "       // transform unnormalized light direction into tangent space\n"
1463 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 "       //  normalize it per pixel)\n"
1465 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1476 "#endif\n"
1477 "\n"
1478 "       // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef USEFOG\n"
1487 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1489 "#endif\n"
1490 "\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1493 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1494 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1495 "#endif\n"
1496 "\n"
1497 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1499 "\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef USEREFLECTION\n"
1505 "       ModelViewProjectionPosition = gl_Position;\n"
1506 "#endif\n"
1507 "}\n"
1508 "#endif // VERTEX_SHADER\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1518 "#endif\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1523 "#ifdef USEGLOW\n"
1524 "uniform myhalf3 Color_Glow;\n"
1525 "#endif\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1532 "#endif\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1537 "#endif\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1540 "#endif\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1543 "#endif\n"
1544 "void main(void)\n"
1545 "{\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 "       // apply offsetmapping\n"
1548 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1550 "#endif\n"
1551 "\n"
1552 "       // combine the diffuse textures (base, pants, shirt)\n"
1553 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 "       if (color.a < 0.5)\n"
1556 "               discard;\n"
1557 "#endif\n"
1558 "       color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1561 "#endif\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1567 "       color.a = 1.0;\n"
1568 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1569 "#endif\n"
1570 "\n"
1571 "       // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1574 "#else\n"
1575 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1576 "#endif\n"
1577 "\n"
1578 "       // get the material colors\n"
1579 "       myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1583 "# else\n"
1584 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1585 "# endif\n"
1586 "#endif\n"
1587 "\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1593 "#endif\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 "       // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1607 "#else\n"
1608 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1610 "#endif\n"
1611 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1612 "#endif\n"
1613 "#else\n"
1614 "       color.rgb = diffusetex * Color_Ambient;\n"
1615 "#endif\n"
1616 "       color.rgb *= LightColor;\n"
1617 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1620 "#endif\n"
1621 "# ifdef USECUBEFILTER\n"
1622 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1623 "# endif\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1630 "#define SHADING\n"
1631 "#ifdef USEDIFFUSE\n"
1632 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1633 "#endif\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1637 "#define SHADING\n"
1638 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 "       // convert modelspace light vector to tangentspace\n"
1642 "       myhalf3 lightnormal;\n"
1643 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1658 "#define SHADING\n"
1659 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1662 "#endif\n"
1663 "\n"
1664 "\n"
1665 "\n"
1666 "\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 "       color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "\n"
1680 "#ifdef SHADING\n"
1681 "# ifdef USEDIFFUSE\n"
1682 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "#  ifdef USESPECULAR\n"
1684 "#   ifdef USEEXACTSPECULARMATH\n"
1685 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1686 "#   else\n"
1687 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1689 "#   endif\n"
1690 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1691 "#  else\n"
1692 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1693 "#  endif\n"
1694 "# else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "# endif\n"
1697 "#endif\n"
1698 "\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1701 "#endif\n"
1702 "\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1707 "#endif\n"
1708 "\n"
1709 "#ifdef USEGLOW\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1712 "#else\n"
1713 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1714 "#endif\n"
1715 "#endif\n"
1716 "\n"
1717 "#ifdef USEFOG\n"
1718 "       color.rgb = FogVertex(color.rgb);\n"
1719 "#endif\n"
1720 "\n"
1721 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1722 "#ifdef USEREFLECTION\n"
1723 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 "       // FIXME temporary hack to detect the case that the reflection\n"
1728 "       // gets blackened at edges due to leaving the area that contains actual\n"
1729 "       // content.\n"
1730 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1731 "       // 'appening.\n"
1732 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1738 "#endif\n"
1739 "\n"
1740 "       gl_FragColor = vec4(color);\n"
1741 "}\n"
1742 "#endif // FRAGMENT_SHADER\n"
1743 "\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1753 ;
1754
1755 /*
1756 =========================================================================================================================================================
1757
1758
1759
1760 =========================================================================================================================================================
1761
1762
1763
1764 =========================================================================================================================================================
1765
1766
1767
1768 =========================================================================================================================================================
1769
1770
1771
1772 =========================================================================================================================================================
1773
1774
1775
1776 =========================================================================================================================================================
1777
1778
1779
1780 =========================================================================================================================================================
1781 */
1782
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1787 "\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1791 "#endif\n"
1792 "\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1794 "# define USEFOG\n"
1795 "#endif\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1798 "#endif\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1801 "#endif\n"
1802 "\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1804 "#ifdef HLSL\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1808 "#else\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1810 "#endif\n"
1811 "#endif\n"
1812 "\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1815 "void main\n"
1816 "(\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1821 ")\n"
1822 "{\n"
1823 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 "       Depth = gl_Position.z;\n"
1825 "}\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1829 "void main\n"
1830 "(\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1833 ")\n"
1834 "{\n"
1835 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1837 "       temp.yz -= floor(temp.yz);\n"
1838 "       gl_FragColor = float4(temp,0);\n"
1839 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1840 "}\n"
1841 "#endif\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1843 "\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1849 "void main\n"
1850 "(\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1855 ")\n"
1856 "{\n"
1857 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1859 "}\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1863 "void main\n"
1864 "(\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_FragColor = gl_FrontColor;\n"
1870 "}\n"
1871 "#endif\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1873 "\n"
1874 "\n"
1875 "\n"
1876 "\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1878 "\n"
1879 "#ifdef VERTEX_SHADER\n"
1880 "void main\n"
1881 "(\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1889 ")\n"
1890 "{\n"
1891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1893 "#ifdef USEBLOOM\n"
1894 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1895 "#endif\n"
1896 "}\n"
1897 "#endif\n"
1898 "\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1900 "void main\n"
1901 "(\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1905 "#ifdef USEBLOOM\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1907 "#endif\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1910 "#endif\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1913 "#endif\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1916 "#endif\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1928 "#ifdef USEBLOOM\n"
1929 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1930 "#endif\n"
1931 "#ifdef USEVIEWTINT\n"
1932 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1933 "#endif\n"
1934 "\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1938 "       float sobel = 1.0;\n"
1939 "       // float2 ts = textureSize(Texture_First, 0);\n"
1940 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 "       float2 px = PixelSize;\n"
1942 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1944 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1947 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1950 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1953 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1971 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1972 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1974 "#endif\n"
1975 "\n"
1976 "#ifdef USESATURATION\n"
1977 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1981 "#endif\n"
1982 "\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1987 "#endif\n"
1988 "}\n"
1989 "#endif\n"
1990 "#else // !MODE_POSTPROCESS\n"
1991 "\n"
1992 "\n"
1993 "\n"
1994 "\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1997 "void main\n"
1998 "(\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "out float4 gl_FrontColor : COLOR,\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "out float2 TexCoord2 : TEXCOORD1\n"
2008 ")\n"
2009 "{\n"
2010 "#ifdef HLSL\n"
2011 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2012 "#else\n"
2013 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2014 "#endif\n"
2015 "#ifdef USEDIFFUSE\n"
2016 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2017 "#endif\n"
2018 "#ifdef USESPECULAR\n"
2019 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2020 "#endif\n"
2021 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2022 "}\n"
2023 "#endif\n"
2024 "\n"
2025 "#ifdef FRAGMENT_SHADER\n"
2026 "\n"
2027 "void main\n"
2028 "(\n"
2029 "float4 gl_FrontColor : COLOR0,\n"
2030 "float2 TexCoord1 : TEXCOORD0,\n"
2031 "float2 TexCoord2 : TEXCOORD1,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2034 "#endif\n"
2035 "#ifdef USESPECULAR\n"
2036 "uniform sampler Texture_Second : register(s1),\n"
2037 "#endif\n"
2038 "out float4 gl_FragColor : COLOR\n"
2039 ")\n"
2040 "{\n"
2041 "       gl_FragColor = gl_FrontColor;\n"
2042 "#ifdef USEDIFFUSE\n"
2043 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2044 "#endif\n"
2045 "\n"
2046 "#ifdef USESPECULAR\n"
2047 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2048 "# ifdef USECOLORMAPPING\n"
2049 "       gl_FragColor *= tex2;\n"
2050 "# endif\n"
2051 "# ifdef USEGLOW\n"
2052 "       gl_FragColor += tex2;\n"
2053 "# endif\n"
2054 "# ifdef USEVERTEXTEXTUREBLEND\n"
2055 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2056 "# endif\n"
2057 "#endif\n"
2058 "}\n"
2059 "#endif\n"
2060 "#else // !MODE_GENERIC\n"
2061 "\n"
2062 "\n"
2063 "\n"
2064 "\n"
2065 "#ifdef MODE_BLOOMBLUR\n"
2066 "#ifdef VERTEX_SHADER\n"
2067 "void main\n"
2068 "(\n"
2069 "float4 gl_Vertex : POSITION,\n"
2070 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2071 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2072 "out float4 gl_Position : POSITION,\n"
2073 "out float2 TexCoord : TEXCOORD0\n"
2074 ")\n"
2075 "{\n"
2076 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2077 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2078 "}\n"
2079 "#endif\n"
2080 "\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2082 "\n"
2083 "void main\n"
2084 "(\n"
2085 "float2 TexCoord : TEXCOORD0,\n"
2086 "uniform sampler Texture_First : register(s0),\n"
2087 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       int i;\n"
2092 "       float2 tc = TexCoord;\n"
2093 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2094 "       tc += BloomBlur_Parameters.xy;\n"
2095 "       for (i = 1;i < SAMPLES;i++)\n"
2096 "       {\n"
2097 "               color += tex2D(Texture_First, tc).rgb;\n"
2098 "               tc += BloomBlur_Parameters.xy;\n"
2099 "       }\n"
2100 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2101 "}\n"
2102 "#endif\n"
2103 "#else // !MODE_BLOOMBLUR\n"
2104 "#ifdef MODE_REFRACTION\n"
2105 "#ifdef VERTEX_SHADER\n"
2106 "void main\n"
2107 "(\n"
2108 "float4 gl_Vertex : POSITION,\n"
2109 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2110 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2111 "uniform float4x4 TexMatrix : register(c0),\n"
2112 "uniform float3 EyePosition : register(c24),\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0,\n"
2115 "out float3 EyeVector : TEXCOORD1,\n"
2116 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2117 ")\n"
2118 "{\n"
2119 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2120 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 "       ModelViewProjectionPosition = gl_Position;\n"
2122 "}\n"
2123 "#endif\n"
2124 "\n"
2125 "#ifdef FRAGMENT_SHADER\n"
2126 "void main\n"
2127 "(\n"
2128 "float2 TexCoord : TEXCOORD0,\n"
2129 "float3 EyeVector : TEXCOORD1,\n"
2130 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2131 "uniform sampler Texture_Normal : register(s0),\n"
2132 "uniform sampler Texture_Refraction : register(s3),\n"
2133 "uniform sampler Texture_Reflection : register(s7),\n"
2134 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2135 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2136 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2137 "uniform float4 RefractColor : register(c29),\n"
2138 "out float4 gl_FragColor : COLOR\n"
2139 ")\n"
2140 "{\n"
2141 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2142 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2143 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2144 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2145 "       // FIXME temporary hack to detect the case that the reflection\n"
2146 "       // gets blackened at edges due to leaving the area that contains actual\n"
2147 "       // content.\n"
2148 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2149 "       // 'appening.\n"
2150 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2151 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2152 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2153 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2154 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2155 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2156 "}\n"
2157 "#endif\n"
2158 "#else // !MODE_REFRACTION\n"
2159 "\n"
2160 "\n"
2161 "\n"
2162 "\n"
2163 "#ifdef MODE_WATER\n"
2164 "#ifdef VERTEX_SHADER\n"
2165 "\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2172 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2173 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2174 "uniform float4x4 TexMatrix : register(c0),\n"
2175 "uniform float3 EyePosition : register(c24),\n"
2176 "out float4 gl_Position : POSITION,\n"
2177 "out float2 TexCoord : TEXCOORD0,\n"
2178 "out float3 EyeVector : TEXCOORD1,\n"
2179 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2180 ")\n"
2181 "{\n"
2182 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2183 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2184 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2185 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2186 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2187 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 "       ModelViewProjectionPosition = gl_Position;\n"
2189 "}\n"
2190 "#endif\n"
2191 "\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2193 "void main\n"
2194 "(\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler Texture_Normal : register(s0),\n"
2199 "uniform sampler Texture_Refraction : register(s3),\n"
2200 "uniform sampler Texture_Reflection : register(s7),\n"
2201 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2202 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2203 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2204 "uniform float4 RefractColor : register(c29),\n"
2205 "uniform float4 ReflectColor : register(c26),\n"
2206 "uniform float ReflectFactor : register(c27),\n"
2207 "uniform float ReflectOffset : register(c28),\n"
2208 "out float4 gl_FragColor : COLOR\n"
2209 ")\n"
2210 "{\n"
2211 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2212 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2213 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2214 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2215 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2216 "       // FIXME temporary hack to detect the case that the reflection\n"
2217 "       // gets blackened at edges due to leaving the area that contains actual\n"
2218 "       // content.\n"
2219 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2220 "       // 'appening.\n"
2221 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2222 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2223 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2224 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2225 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2226 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2227 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2228 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2229 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2230 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2231 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2232 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2233 "}\n"
2234 "#endif\n"
2235 "#else // !MODE_WATER\n"
2236 "\n"
2237 "\n"
2238 "\n"
2239 "\n"
2240 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2241 "\n"
2242 "// fragment shader specific:\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2244 "\n"
2245 "#ifdef USEFOG\n"
2246 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2247 "{\n"
2248 "       float fogfrac;\n"
2249 "#ifdef USEFOGHEIGHTTEXTURE\n"
2250 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2251 "       fogfrac = fogheightpixel.a;\n"
2252 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2253 "#else\n"
2254 "# ifdef USEFOGOUTSIDE\n"
2255 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2256 "# else\n"
2257 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2258 "# endif\n"
2259 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2260 "#endif\n"
2261 "}\n"
2262 "#endif\n"
2263 "\n"
2264 "#ifdef USEOFFSETMAPPING\n"
2265 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2266 "{\n"
2267 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2268 "       // 14 sample relief mapping: linear search and then binary search\n"
2269 "       // this basically steps forward a small amount repeatedly until it finds\n"
2270 "       // itself inside solid, then jitters forward and back using decreasing\n"
2271 "       // amounts to find the impact\n"
2272 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2273 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2274 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2275 "       float3 RT = float3(TexCoord, 1);\n"
2276 "       OffsetVector *= 0.1;\n"
2277 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2278 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2279 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2280 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2281 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2287 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2288 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2289 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2290 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2291 "       return RT.xy;\n"
2292 "#else\n"
2293 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2294 "       // this basically moves forward the full distance, and then backs up based\n"
2295 "       // on height of samples\n"
2296 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2297 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2298 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2299 "       TexCoord += OffsetVector;\n"
2300 "       OffsetVector *= 0.333;\n"
2301 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2302 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2303 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2304 "       return TexCoord;\n"
2305 "#endif\n"
2306 "}\n"
2307 "#endif // USEOFFSETMAPPING\n"
2308 "\n"
2309 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2310 "#if defined(USESHADOWMAP2D)\n"
2311 "# ifdef USESHADOWMAPORTHO\n"
2312 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2313 "# else\n"
2314 "#  ifdef USESHADOWMAPVSDCT\n"
2315 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2316 "{\n"
2317 "       float3 adir = abs(dir);\n"
2318 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2319 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2320 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2321 "}\n"
2322 "#  else\n"
2323 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2324 "{\n"
2325 "       float3 adir = abs(dir);\n"
2326 "       float ma = adir.z;\n"
2327 "       float4 proj = float4(dir, 2.5);\n"
2328 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2329 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2330 "#ifdef HLSL\n"
2331 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2332 "#else\n"
2333 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2334 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2335 "#endif\n"
2336 "}\n"
2337 "#  endif\n"
2338 "# endif\n"
2339 "#endif // defined(USESHADOWMAP2D)\n"
2340 "\n"
2341 "# ifdef USESHADOWMAP2D\n"
2342 "#ifdef USESHADOWMAPVSDCT\n"
2343 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2344 "#else\n"
2345 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2346 "#endif\n"
2347 "{\n"
2348 "#ifdef USESHADOWMAPVSDCT\n"
2349 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2350 "#else\n"
2351 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2352 "#endif\n"
2353 "       float f;\n"
2354 "\n"
2355 "#  ifdef USESHADOWSAMPLER\n"
2356 "#    ifdef USESHADOWMAPPCF\n"
2357 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2358 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2359 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2360 "#    else\n"
2361 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2362 "#    endif\n"
2363 "#  else\n"
2364 "#    ifdef USESHADOWMAPPCF\n"
2365 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2366 "#      ifdef GL_ARB_texture_gather\n"
2367 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2368 "#      else\n"
2369 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2370 "#      endif\n"
2371 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2372 "#      if USESHADOWMAPPCF > 1\n"
2373 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2374 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2375 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2376 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2377 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2378 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2379 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2380 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2381 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2382 "       float4 locols = float4(group1.ab, group3.ab);\n"
2383 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2384 "       locols.yz += group2.ab;\n"
2385 "       hicols.yz += group8.rg;\n"
2386 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2387 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2388 "                               lerp(locols, hicols, offset.y);\n"
2389 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2390 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2391 "       f = dot(cols, float4(1.0/25.0));\n"
2392 "#      else\n"
2393 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2394 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2395 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2396 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2397 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2398 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2399 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2400 "#      endif\n"
2401 "#     else\n"
2402 "#      ifdef GL_EXT_gpu_shader4\n"
2403 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2404 "#      else\n"
2405 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2406 "#      endif\n"
2407 "#      if USESHADOWMAPPCF > 1\n"
2408 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2409 "       center *= ShadowMap_TextureScale;\n"
2410 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2411 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2412 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2413 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2414 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2415 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2416 "#      else\n"
2417 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2418 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2419 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2420 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2421 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2422 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2423 "#      endif\n"
2424 "#     endif\n"
2425 "#    else\n"
2426 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2427 "#    endif\n"
2428 "#  endif\n"
2429 "#  ifdef USESHADOWMAPORTHO\n"
2430 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2431 "#  else\n"
2432 "       return f;\n"
2433 "#  endif\n"
2434 "}\n"
2435 "# endif\n"
2436 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2437 "#endif // FRAGMENT_SHADER\n"
2438 "\n"
2439 "\n"
2440 "\n"
2441 "\n"
2442 "#ifdef MODE_DEFERREDGEOMETRY\n"
2443 "#ifdef VERTEX_SHADER\n"
2444 "void main\n"
2445 "(\n"
2446 "float4 gl_Vertex : POSITION,\n"
2447 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "float4 gl_Color : COLOR0,\n"
2450 "#endif\n"
2451 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2452 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2453 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2454 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2455 "uniform float4x4 TexMatrix : register(c0),\n"
2456 "#ifdef USEVERTEXTEXTUREBLEND\n"
2457 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2458 "#endif\n"
2459 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2460 "#ifdef USEOFFSETMAPPING\n"
2461 "uniform float3 EyePosition : register(c24),\n"
2462 "#endif\n"
2463 "out float4 gl_Position : POSITION,\n"
2464 "out float4 gl_FrontColor : COLOR,\n"
2465 "out float4 TexCoordBoth : TEXCOORD0,\n"
2466 "#ifdef USEOFFSETMAPPING\n"
2467 "out float3 EyeVector : TEXCOORD2,\n"
2468 "#endif\n"
2469 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2470 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2471 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2472 ")\n"
2473 "{\n"
2474 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2476 "#ifdef HLSL\n"
2477 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2478 "#else\n"
2479 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2480 "#endif\n"
2481 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2482 "#endif\n"
2483 "\n"
2484 "       // transform unnormalized eye direction into tangent space\n"
2485 "#ifdef USEOFFSETMAPPING\n"
2486 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2487 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2488 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2489 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2490 "#endif\n"
2491 "\n"
2492 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2493 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2494 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2496 "}\n"
2497 "#endif // VERTEX_SHADER\n"
2498 "\n"
2499 "#ifdef FRAGMENT_SHADER\n"
2500 "void main\n"
2501 "(\n"
2502 "float4 TexCoordBoth : TEXCOORD0,\n"
2503 "float3 EyeVector : TEXCOORD2,\n"
2504 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2505 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2506 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2507 "uniform sampler Texture_Normal : register(s0),\n"
2508 "#ifdef USEALPHAKILL\n"
2509 "uniform sampler Texture_Color : register(s1),\n"
2510 "#endif\n"
2511 "uniform sampler Texture_Gloss : register(s2),\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2514 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2515 "#endif\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "uniform float OffsetMapping_Scale : register(c24),\n"
2518 "#endif\n"
2519 "uniform half SpecularPower : register(c36),\n"
2520 "out float4 gl_FragColor : COLOR\n"
2521 ")\n"
2522 "{\n"
2523 "       float2 TexCoord = TexCoordBoth.xy;\n"
2524 "#ifdef USEOFFSETMAPPING\n"
2525 "       // apply offsetmapping\n"
2526 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2527 "#define TexCoord TexCoordOffset\n"
2528 "#endif\n"
2529 "\n"
2530 "#ifdef USEALPHAKILL\n"
2531 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2532 "               discard;\n"
2533 "#endif\n"
2534 "\n"
2535 "#ifdef USEVERTEXTEXTUREBLEND\n"
2536 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2537 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2538 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2539 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2540 "#endif\n"
2541 "\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2544 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2545 "#else\n"
2546 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2547 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2548 "#endif\n"
2549 "\n"
2550 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2551 "}\n"
2552 "#endif // FRAGMENT_SHADER\n"
2553 "#else // !MODE_DEFERREDGEOMETRY\n"
2554 "\n"
2555 "\n"
2556 "\n"
2557 "\n"
2558 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2559 "#ifdef VERTEX_SHADER\n"
2560 "void main\n"
2561 "(\n"
2562 "float4 gl_Vertex : POSITION,\n"
2563 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2564 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2565 "out float4 gl_Position : POSITION,\n"
2566 "out float4 ModelViewPosition : TEXCOORD0\n"
2567 ")\n"
2568 "{\n"
2569 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2570 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2571 "}\n"
2572 "#endif // VERTEX_SHADER\n"
2573 "\n"
2574 "#ifdef FRAGMENT_SHADER\n"
2575 "void main\n"
2576 "(\n"
2577 "#ifdef HLSL\n"
2578 "float2 Pixel : VPOS,\n"
2579 "#else\n"
2580 "float2 Pixel : WPOS,\n"
2581 "#endif\n"
2582 "float4 ModelViewPosition : TEXCOORD0,\n"
2583 "uniform float4x4 ViewToLight : register(c44),\n"
2584 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2585 "uniform float3 LightPosition : register(c23),\n"
2586 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2587 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2588 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2589 "#ifdef USESPECULAR\n"
2590 "uniform half3 DeferredColor_Specular : register(c11),\n"
2591 "uniform half SpecularPower : register(c36),\n"
2592 "#endif\n"
2593 "uniform sampler Texture_Attenuation : register(s9),\n"
2594 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2595 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2596 "\n"
2597 "#ifdef USECUBEFILTER\n"
2598 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2599 "#endif\n"
2600 "\n"
2601 "#ifdef USESHADOWMAP2D\n"
2602 "# ifdef USESHADOWSAMPLER\n"
2603 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2604 "# else\n"
2605 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2606 "# endif\n"
2607 "#endif\n"
2608 "\n"
2609 "#ifdef USESHADOWMAPVSDCT\n"
2610 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2611 "#endif\n"
2612 "\n"
2613 "#if defined(USESHADOWMAP2D)\n"
2614 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2615 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2616 "#endif\n"
2617 "\n"
2618 "out float4 gl_FragData0 : COLOR0,\n"
2619 "out float4 gl_FragData1 : COLOR1\n"
2620 ")\n"
2621 "{\n"
2622 "       // calculate viewspace pixel position\n"
2623 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2624 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2625 "       float3 position;\n"
2626 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2627 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2628 "       // decode viewspace pixel normal\n"
2629 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2630 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2631 "       // surfacenormal = pixel normal in viewspace\n"
2632 "       // LightVector = pixel to light in viewspace\n"
2633 "       // CubeVector = position in lightspace\n"
2634 "       // eyevector = pixel to view in viewspace\n"
2635 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2636 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2637 "#ifdef USEDIFFUSE\n"
2638 "       // calculate diffuse shading\n"
2639 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2640 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2641 "#endif\n"
2642 "#ifdef USESPECULAR\n"
2643 "       // calculate directional shading\n"
2644 "       float3 eyevector = position * -1.0;\n"
2645 "#  ifdef USEEXACTSPECULARMATH\n"
2646 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2647 "#  else\n"
2648 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2649 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2650 "#  endif\n"
2651 "#endif\n"
2652 "\n"
2653 "#if defined(USESHADOWMAP2D)\n"
2654 "       fade *= ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2655 "#ifdef USESHADOWMAPVSDCT\n"
2656 ", Texture_CubeProjection\n"
2657 "#endif\n"
2658 "       );\n"
2659 "#endif\n"
2660 "\n"
2661 "#ifdef USEDIFFUSE\n"
2662 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2663 "#else\n"
2664 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2665 "#endif\n"
2666 "#ifdef USESPECULAR\n"
2667 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2668 "#else\n"
2669 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2670 "#endif\n"
2671 "\n"
2672 "# ifdef USECUBEFILTER\n"
2673 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2674 "       gl_FragData0.rgb *= cubecolor;\n"
2675 "       gl_FragData1.rgb *= cubecolor;\n"
2676 "# endif\n"
2677 "}\n"
2678 "#endif // FRAGMENT_SHADER\n"
2679 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2680 "\n"
2681 "\n"
2682 "\n"
2683 "\n"
2684 "#ifdef VERTEX_SHADER\n"
2685 "void main\n"
2686 "(\n"
2687 "float4 gl_Vertex : POSITION,\n"
2688 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2689 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2690 "float4 gl_Color : COLOR0,\n"
2691 "#endif\n"
2692 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2693 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2694 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2695 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2696 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2697 "\n"
2698 "uniform float3 EyePosition : register(c24),\n"
2699 "uniform float4x4 TexMatrix : register(c0),\n"
2700 "#ifdef USEVERTEXTEXTUREBLEND\n"
2701 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2702 "#endif\n"
2703 "#ifdef MODE_LIGHTSOURCE\n"
2704 "uniform float4x4 ModelToLight : register(c20),\n"
2705 "#endif\n"
2706 "#ifdef MODE_LIGHTSOURCE\n"
2707 "uniform float3 LightPosition : register(c27),\n"
2708 "#endif\n"
2709 "#ifdef MODE_LIGHTDIRECTION\n"
2710 "uniform float3 LightDir : register(c26),\n"
2711 "#endif\n"
2712 "uniform float4 FogPlane : register(c25),\n"
2713 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2714 "uniform float3 LightPosition : register(c27),\n"
2715 "#endif\n"
2716 "#ifdef USESHADOWMAPORTHO\n"
2717 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2718 "#endif\n"
2719 "\n"
2720 "out float4 gl_FrontColor : COLOR,\n"
2721 "out float4 TexCoordBoth : TEXCOORD0,\n"
2722 "#ifdef USELIGHTMAP\n"
2723 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2724 "#endif\n"
2725 "#ifdef USEEYEVECTOR\n"
2726 "out float3 EyeVector : TEXCOORD2,\n"
2727 "#endif\n"
2728 "#ifdef USEREFLECTION\n"
2729 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2730 "#endif\n"
2731 "#ifdef USEFOG\n"
2732 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2733 "#endif\n"
2734 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2735 "out float3 LightVector : TEXCOORD1,\n"
2736 "#endif\n"
2737 "#ifdef MODE_LIGHTSOURCE\n"
2738 "out float3 CubeVector : TEXCOORD3,\n"
2739 "#endif\n"
2740 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2741 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2742 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2743 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2744 "#endif\n"
2745 "#ifdef USESHADOWMAPORTHO\n"
2746 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2747 "#endif\n"
2748 "out float4 gl_Position : POSITION\n"
2749 ")\n"
2750 "{\n"
2751 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2752 "#ifdef HLSL\n"
2753 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2754 "#else\n"
2755 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2756 "#endif\n"
2757 "#endif\n"
2758 "       // copy the surface texcoord\n"
2759 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2760 "#ifdef USEVERTEXTEXTUREBLEND\n"
2761 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2762 "#endif\n"
2763 "#ifdef USELIGHTMAP\n"
2764 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2765 "#endif\n"
2766 "\n"
2767 "#ifdef MODE_LIGHTSOURCE\n"
2768 "       // transform vertex position into light attenuation/cubemap space\n"
2769 "       // (-1 to +1 across the light box)\n"
2770 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2771 "\n"
2772 "# ifdef USEDIFFUSE\n"
2773 "       // transform unnormalized light direction into tangent space\n"
2774 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2775 "       //  normalize it per pixel)\n"
2776 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2777 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2778 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2779 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2784 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2785 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2786 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2787 "#endif\n"
2788 "\n"
2789 "       // transform unnormalized eye direction into tangent space\n"
2790 "#ifdef USEEYEVECTOR\n"
2791 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2792 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2793 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2794 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2795 "#endif\n"
2796 "\n"
2797 "#ifdef USEFOG\n"
2798 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2799 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2800 "#endif\n"
2801 "\n"
2802 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2803 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2804 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2805 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2806 "#endif\n"
2807 "\n"
2808 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2809 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2810 "\n"
2811 "#ifdef USESHADOWMAPORTHO\n"
2812 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2813 "#endif\n"
2814 "\n"
2815 "#ifdef USEREFLECTION\n"
2816 "       ModelViewProjectionPosition = gl_Position;\n"
2817 "#endif\n"
2818 "}\n"
2819 "#endif // VERTEX_SHADER\n"
2820 "\n"
2821 "\n"
2822 "\n"
2823 "\n"
2824 "#ifdef FRAGMENT_SHADER\n"
2825 "void main\n"
2826 "(\n"
2827 "#ifdef USEDEFERREDLIGHTMAP\n"
2828 "#ifdef HLSL\n"
2829 "float2 Pixel : VPOS,\n"
2830 "#else\n"
2831 "float2 Pixel : WPOS,\n"
2832 "#endif\n"
2833 "#endif\n"
2834 "float4 gl_FrontColor : COLOR,\n"
2835 "float4 TexCoordBoth : TEXCOORD0,\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "float2 TexCoordLightmap : TEXCOORD1,\n"
2838 "#endif\n"
2839 "#ifdef USEEYEVECTOR\n"
2840 "float3 EyeVector : TEXCOORD2,\n"
2841 "#endif\n"
2842 "#ifdef USEREFLECTION\n"
2843 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2844 "#endif\n"
2845 "#ifdef USEFOG\n"
2846 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2847 "#endif\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2849 "float3 LightVector : TEXCOORD1,\n"
2850 "#endif\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "float3 CubeVector : TEXCOORD3,\n"
2853 "#endif\n"
2854 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2855 "float4 ModelViewPosition : TEXCOORD0,\n"
2856 "#endif\n"
2857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2858 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2859 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2860 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2861 "#endif\n"
2862 "#ifdef USESHADOWMAPORTHO\n"
2863 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2864 "#endif\n"
2865 "\n"
2866 "uniform sampler Texture_Normal : register(s0),\n"
2867 "uniform sampler Texture_Color : register(s1),\n"
2868 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2869 "uniform sampler Texture_Gloss : register(s2),\n"
2870 "#endif\n"
2871 "#ifdef USEGLOW\n"
2872 "uniform sampler Texture_Glow : register(s3),\n"
2873 "#endif\n"
2874 "#ifdef USEVERTEXTEXTUREBLEND\n"
2875 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2876 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2877 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2878 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2879 "#endif\n"
2880 "#ifdef USEGLOW\n"
2881 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2882 "#endif\n"
2883 "#endif\n"
2884 "#ifdef USECOLORMAPPING\n"
2885 "uniform sampler Texture_Pants : register(s4),\n"
2886 "uniform sampler Texture_Shirt : register(s7),\n"
2887 "#endif\n"
2888 "#ifdef USEFOG\n"
2889 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2890 "uniform sampler Texture_FogMask : register(s8),\n"
2891 "#endif\n"
2892 "#ifdef USELIGHTMAP\n"
2893 "uniform sampler Texture_Lightmap : register(s9),\n"
2894 "#endif\n"
2895 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2896 "uniform sampler Texture_Deluxemap : register(s10),\n"
2897 "#endif\n"
2898 "#ifdef USEREFLECTION\n"
2899 "uniform sampler Texture_Reflection : register(s7),\n"
2900 "#endif\n"
2901 "\n"
2902 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2903 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2904 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2905 "#endif\n"
2906 "#ifdef USEDEFERREDLIGHTMAP\n"
2907 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2908 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2909 "#endif\n"
2910 "\n"
2911 "#ifdef USECOLORMAPPING\n"
2912 "uniform half3 Color_Pants : register(c7),\n"
2913 "uniform half3 Color_Shirt : register(c8),\n"
2914 "#endif\n"
2915 "#ifdef USEFOG\n"
2916 "uniform float3 FogColor : register(c16),\n"
2917 "uniform float FogRangeRecip : register(c20),\n"
2918 "uniform float FogPlaneViewDist : register(c19),\n"
2919 "uniform float FogHeightFade : register(c17),\n"
2920 "#endif\n"
2921 "\n"
2922 "#ifdef USEOFFSETMAPPING\n"
2923 "uniform float OffsetMapping_Scale : register(c24),\n"
2924 "#endif\n"
2925 "\n"
2926 "#ifdef USEDEFERREDLIGHTMAP\n"
2927 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2928 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2929 "uniform half3 DeferredMod_Specular : register(c13),\n"
2930 "#endif\n"
2931 "uniform half3 Color_Ambient : register(c3),\n"
2932 "uniform half3 Color_Diffuse : register(c4),\n"
2933 "uniform half3 Color_Specular : register(c5),\n"
2934 "uniform half SpecularPower : register(c36),\n"
2935 "#ifdef USEGLOW\n"
2936 "uniform half3 Color_Glow : register(c6),\n"
2937 "#endif\n"
2938 "uniform half Alpha : register(c0),\n"
2939 "#ifdef USEREFLECTION\n"
2940 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2941 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2942 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2943 "uniform half4 ReflectColor : register(c26),\n"
2944 "#endif\n"
2945 "#ifdef USEREFLECTCUBE\n"
2946 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2947 "uniform sampler Texture_ReflectMask : register(s5),\n"
2948 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2949 "#endif\n"
2950 "#ifdef MODE_LIGHTDIRECTION\n"
2951 "uniform half3 LightColor : register(c21),\n"
2952 "#endif\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "uniform half3 LightColor : register(c21),\n"
2955 "#endif\n"
2956 "\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2958 "uniform sampler Texture_Attenuation : register(s9),\n"
2959 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2960 "#endif\n"
2961 "\n"
2962 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2963 "\n"
2964 "#ifdef USESHADOWMAP2D\n"
2965 "# ifdef USESHADOWSAMPLER\n"
2966 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2967 "# else\n"
2968 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2969 "# endif\n"
2970 "#endif\n"
2971 "\n"
2972 "#ifdef USESHADOWMAPVSDCT\n"
2973 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2974 "#endif\n"
2975 "\n"
2976 "#if defined(USESHADOWMAP2D)\n"
2977 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2978 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2979 "#endif\n"
2980 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2981 "\n"
2982 "out float4 gl_FragColor : COLOR\n"
2983 ")\n"
2984 "{\n"
2985 "       float2 TexCoord = TexCoordBoth.xy;\n"
2986 "#ifdef USEVERTEXTEXTUREBLEND\n"
2987 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2988 "#endif\n"
2989 "#ifdef USEOFFSETMAPPING\n"
2990 "       // apply offsetmapping\n"
2991 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2992 "#define TexCoord TexCoordOffset\n"
2993 "#endif\n"
2994 "\n"
2995 "       // combine the diffuse textures (base, pants, shirt)\n"
2996 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2997 "#ifdef USEALPHAKILL\n"
2998 "       if (color.a < 0.5)\n"
2999 "               discard;\n"
3000 "#endif\n"
3001 "       color.a *= Alpha;\n"
3002 "#ifdef USECOLORMAPPING\n"
3003 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3004 "#endif\n"
3005 "#ifdef USEVERTEXTEXTUREBLEND\n"
3006 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3007 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3008 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3009 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3010 "       color.a = 1.0;\n"
3011 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3012 "#endif\n"
3013 "\n"
3014 "       // get the surface normal\n"
3015 "#ifdef USEVERTEXTEXTUREBLEND\n"
3016 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3017 "#else\n"
3018 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3019 "#endif\n"
3020 "\n"
3021 "       // get the material colors\n"
3022 "       half3 diffusetex = color.rgb;\n"
3023 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3024 "# ifdef USEVERTEXTEXTUREBLEND\n"
3025 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3026 "# else\n"
3027 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3028 "# endif\n"
3029 "#endif\n"
3030 "\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3033 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3034 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3035 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3036 "#endif\n"
3037 "\n"
3038 "\n"
3039 "\n"
3040 "\n"
3041 "#ifdef MODE_LIGHTSOURCE\n"
3042 "       // light source\n"
3043 "#ifdef USEDIFFUSE\n"
3044 "       half3 lightnormal = half3(normalize(LightVector));\n"
3045 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3046 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3047 "#ifdef USESPECULAR\n"
3048 "#ifdef USEEXACTSPECULARMATH\n"
3049 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3050 "#else\n"
3051 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3052 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3053 "#endif\n"
3054 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3055 "#endif\n"
3056 "#else\n"
3057 "       color.rgb = diffusetex * Color_Ambient;\n"
3058 "#endif\n"
3059 "       color.rgb *= LightColor;\n"
3060 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3063 "#ifdef USESHADOWMAPVSDCT\n"
3064 ", Texture_CubeProjection\n"
3065 "#endif\n"
3066 "       ));\n"
3067 "\n"
3068 "#endif\n"
3069 "# ifdef USECUBEFILTER\n"
3070 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3071 "# endif\n"
3072 "\n"
3073 "#ifdef USESHADOWMAP2D\n"
3074 "#ifdef USESHADOWMAPVSDCT\n"
3075 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3076 "#else\n"
3077 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3078 "#endif\n"
3079 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3080 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3081 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3082 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3083 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3084 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3085 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3086 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3087 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3088 "//     color.r = half(shadowmaptc.z);\n"
3089 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3090 "//     color.r = half(shadowmaptc.z);\n"
3091 "//     color.r = 1;\n"
3092 "//     color.rgb = abs(CubeVector);\n"
3093 "#endif\n"
3094 "//     color.rgb = half3(1,1,1);\n"
3095 "#endif // MODE_LIGHTSOURCE\n"
3096 "\n"
3097 "\n"
3098 "\n"
3099 "\n"
3100 "#ifdef MODE_LIGHTDIRECTION\n"
3101 "#define SHADING\n"
3102 "#ifdef USEDIFFUSE\n"
3103 "       half3 lightnormal = half3(normalize(LightVector));\n"
3104 "#endif\n"
3105 "#define lightcolor LightColor\n"
3106 "#endif // MODE_LIGHTDIRECTION\n"
3107 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3108 "#define SHADING\n"
3109 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3110 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3111 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3112 "       // convert modelspace light vector to tangentspace\n"
3113 "       half3 lightnormal;\n"
3114 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3115 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3116 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3117 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3118 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3119 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3120 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3121 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3122 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3123 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3124 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3125 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3126 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3127 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3128 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3129 "#define SHADING\n"
3130 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3131 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3132 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3133 "#endif\n"
3134 "\n"
3135 "\n"
3136 "\n"
3137 "\n"
3138 "#ifdef MODE_LIGHTMAP\n"
3139 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3140 "#endif // MODE_LIGHTMAP\n"
3141 "#ifdef MODE_VERTEXCOLOR\n"
3142 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3143 "#endif // MODE_VERTEXCOLOR\n"
3144 "#ifdef MODE_FLATCOLOR\n"
3145 "       color.rgb = diffusetex * Color_Ambient;\n"
3146 "#endif // MODE_FLATCOLOR\n"
3147 "\n"
3148 "\n"
3149 "\n"
3150 "\n"
3151 "#ifdef SHADING\n"
3152 "# ifdef USEDIFFUSE\n"
3153 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3154 "#  ifdef USESPECULAR\n"
3155 "#   ifdef USEEXACTSPECULARMATH\n"
3156 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3157 "#   else\n"
3158 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3159 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3160 "#   endif\n"
3161 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3162 "#  else\n"
3163 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3164 "#  endif\n"
3165 "# else\n"
3166 "       color.rgb = diffusetex * Color_Ambient;\n"
3167 "# endif\n"
3168 "#endif\n"
3169 "\n"
3170 "#ifdef USESHADOWMAPORTHO\n"
3171 "       color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n"
3172 "#endif\n"
3173 "\n"
3174 "#ifdef USEDEFERREDLIGHTMAP\n"
3175 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3176 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3177 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USEGLOW\n"
3181 "#ifdef USEVERTEXTEXTUREBLEND\n"
3182 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3183 "#else\n"
3184 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3185 "#endif\n"
3186 "#endif\n"
3187 "\n"
3188 "#ifdef USEFOG\n"
3189 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3190 "#endif\n"
3191 "\n"
3192 "       // 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"
3193 "#ifdef USEREFLECTION\n"
3194 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3195 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3196 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3197 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3198 "       // FIXME temporary hack to detect the case that the reflection\n"
3199 "       // gets blackened at edges due to leaving the area that contains actual\n"
3200 "       // content.\n"
3201 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3202 "       // 'appening.\n"
3203 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3204 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3205 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3206 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3207 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3208 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3209 "#endif\n"
3210 "\n"
3211 "       gl_FragColor = float4(color);\n"
3212 "}\n"
3213 "#endif // FRAGMENT_SHADER\n"
3214 "\n"
3215 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3216 "#endif // !MODE_DEFERREDGEOMETRY\n"
3217 "#endif // !MODE_WATER\n"
3218 "#endif // !MODE_REFRACTION\n"
3219 "#endif // !MODE_BLOOMBLUR\n"
3220 "#endif // !MODE_GENERIC\n"
3221 "#endif // !MODE_POSTPROCESS\n"
3222 "#endif // !MODE_SHOWDEPTH\n"
3223 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3224 ;
3225
3226 char *glslshaderstring = NULL;
3227 char *cgshaderstring = NULL;
3228 char *hlslshaderstring = NULL;
3229
3230 //=======================================================================================================================================================
3231
3232 typedef struct shaderpermutationinfo_s
3233 {
3234         const char *pretext;
3235         const char *name;
3236 }
3237 shaderpermutationinfo_t;
3238
3239 typedef struct shadermodeinfo_s
3240 {
3241         const char *vertexfilename;
3242         const char *geometryfilename;
3243         const char *fragmentfilename;
3244         const char *pretext;
3245         const char *name;
3246 }
3247 shadermodeinfo_t;
3248
3249 typedef enum shaderpermutation_e
3250 {
3251         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3252         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3253         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3254         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3255         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3256         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3257         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3258         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3259         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3260         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3261         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3262         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3263         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3264         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3265         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3266         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3267         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3268         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3269         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3270         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3271         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3272         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3273         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3274         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3275         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3276         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3277         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3278         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3279         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3280 }
3281 shaderpermutation_t;
3282
3283 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3284 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3285 {
3286         {"#define USEDIFFUSE\n", " diffuse"},
3287         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3288         {"#define USEVIEWTINT\n", " viewtint"},
3289         {"#define USECOLORMAPPING\n", " colormapping"},
3290         {"#define USESATURATION\n", " saturation"},
3291         {"#define USEFOGINSIDE\n", " foginside"},
3292         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3293         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3294         {"#define USEGAMMARAMPS\n", " gammaramps"},
3295         {"#define USECUBEFILTER\n", " cubefilter"},
3296         {"#define USEGLOW\n", " glow"},
3297         {"#define USEBLOOM\n", " bloom"},
3298         {"#define USESPECULAR\n", " specular"},
3299         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3300         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3301         {"#define USEREFLECTION\n", " reflection"},
3302         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3303         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3304         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3305         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3306         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3307         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3308         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3309         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3310         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3311         {"#define USEALPHAKILL\n", " alphakill"},
3312         {"#define USEREFLECTCUBE\n", " reflectcube"},
3313 };
3314
3315 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3316 typedef enum shadermode_e
3317 {
3318         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3319         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3320         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3321         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3322         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3323         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3324         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3325         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3326         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3327         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3328         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3329         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3330         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3331         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3332         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3333         SHADERMODE_COUNT
3334 }
3335 shadermode_t;
3336
3337 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3338 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3339 {
3340         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3341         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3342         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3343         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3344         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3345         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3346         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3347         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3348         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3349         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3350         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3351         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3352         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3353         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3354         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3355 };
3356
3357 #ifdef SUPPORTCG
3358 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3359 {
3360         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3361         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3362         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3363         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3364         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3365         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3366         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3367         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3368         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3369         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3370         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3371         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3372         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3373         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3374         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3375 };
3376 #endif
3377
3378 #ifdef SUPPORTD3D
3379 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3380 {
3381         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3382         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3384         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3388         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3389         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3390         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3391         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3392         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3393         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3394         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3395         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3396 };
3397 #endif
3398
3399 struct r_glsl_permutation_s;
3400 typedef struct r_glsl_permutation_s
3401 {
3402         /// hash lookup data
3403         struct r_glsl_permutation_s *hashnext;
3404         unsigned int mode;
3405         unsigned int permutation;
3406
3407         /// indicates if we have tried compiling this permutation already
3408         qboolean compiled;
3409         /// 0 if compilation failed
3410         int program;
3411         /// locations of detected uniforms in program object, or -1 if not found
3412         int loc_Texture_First;
3413         int loc_Texture_Second;
3414         int loc_Texture_GammaRamps;
3415         int loc_Texture_Normal;
3416         int loc_Texture_Color;
3417         int loc_Texture_Gloss;
3418         int loc_Texture_Glow;
3419         int loc_Texture_SecondaryNormal;
3420         int loc_Texture_SecondaryColor;
3421         int loc_Texture_SecondaryGloss;
3422         int loc_Texture_SecondaryGlow;
3423         int loc_Texture_Pants;
3424         int loc_Texture_Shirt;
3425         int loc_Texture_FogHeightTexture;
3426         int loc_Texture_FogMask;
3427         int loc_Texture_Lightmap;
3428         int loc_Texture_Deluxemap;
3429         int loc_Texture_Attenuation;
3430         int loc_Texture_Cube;
3431         int loc_Texture_Refraction;
3432         int loc_Texture_Reflection;
3433         int loc_Texture_ShadowMap2D;
3434         int loc_Texture_CubeProjection;
3435         int loc_Texture_ScreenDepth;
3436         int loc_Texture_ScreenNormalMap;
3437         int loc_Texture_ScreenDiffuse;
3438         int loc_Texture_ScreenSpecular;
3439         int loc_Texture_ReflectMask;
3440         int loc_Texture_ReflectCube;
3441         int loc_Alpha;
3442         int loc_BloomBlur_Parameters;
3443         int loc_ClientTime;
3444         int loc_Color_Ambient;
3445         int loc_Color_Diffuse;
3446         int loc_Color_Specular;
3447         int loc_Color_Glow;
3448         int loc_Color_Pants;
3449         int loc_Color_Shirt;
3450         int loc_DeferredColor_Ambient;
3451         int loc_DeferredColor_Diffuse;
3452         int loc_DeferredColor_Specular;
3453         int loc_DeferredMod_Diffuse;
3454         int loc_DeferredMod_Specular;
3455         int loc_DistortScaleRefractReflect;
3456         int loc_EyePosition;
3457         int loc_FogColor;
3458         int loc_FogHeightFade;
3459         int loc_FogPlane;
3460         int loc_FogPlaneViewDist;
3461         int loc_FogRangeRecip;
3462         int loc_LightColor;
3463         int loc_LightDir;
3464         int loc_LightPosition;
3465         int loc_OffsetMapping_Scale;
3466         int loc_PixelSize;
3467         int loc_ReflectColor;
3468         int loc_ReflectFactor;
3469         int loc_ReflectOffset;
3470         int loc_RefractColor;
3471         int loc_Saturation;
3472         int loc_ScreenCenterRefractReflect;
3473         int loc_ScreenScaleRefractReflect;
3474         int loc_ScreenToDepth;
3475         int loc_ShadowMap_Parameters;
3476         int loc_ShadowMap_TextureScale;
3477         int loc_SpecularPower;
3478         int loc_UserVec1;
3479         int loc_UserVec2;
3480         int loc_UserVec3;
3481         int loc_UserVec4;
3482         int loc_ViewTintColor;
3483         int loc_ViewToLight;
3484         int loc_ModelToLight;
3485         int loc_TexMatrix;
3486         int loc_BackgroundTexMatrix;
3487         int loc_ModelViewProjectionMatrix;
3488         int loc_ModelViewMatrix;
3489         int loc_PixelToScreenTexCoord;
3490         int loc_ModelToReflectCube;
3491         int loc_ShadowMapMatrix;
3492         int loc_BloomColorSubtract;
3493 }
3494 r_glsl_permutation_t;
3495
3496 #define SHADERPERMUTATION_HASHSIZE 256
3497
3498 /// information about each possible shader permutation
3499 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3500 /// currently selected permutation
3501 r_glsl_permutation_t *r_glsl_permutation;
3502 /// storage for permutations linked in the hash table
3503 memexpandablearray_t r_glsl_permutationarray;
3504
3505 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3506 {
3507         //unsigned int hashdepth = 0;
3508         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3509         r_glsl_permutation_t *p;
3510         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3511         {
3512                 if (p->mode == mode && p->permutation == permutation)
3513                 {
3514                         //if (hashdepth > 10)
3515                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3516                         return p;
3517                 }
3518                 //hashdepth++;
3519         }
3520         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3521         p->mode = mode;
3522         p->permutation = permutation;
3523         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3524         r_glsl_permutationhash[mode][hashindex] = p;
3525         //if (hashdepth > 10)
3526         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3527         return p;
3528 }
3529
3530 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3531 {
3532         char *shaderstring;
3533         if (!filename || !filename[0])
3534                 return NULL;
3535         if (!strcmp(filename, "glsl/default.glsl"))
3536         {
3537                 if (!glslshaderstring)
3538                 {
3539                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3540                         if (glslshaderstring)
3541                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3542                         else
3543                                 glslshaderstring = (char *)builtinshaderstring;
3544                 }
3545                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3546                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3547                 return shaderstring;
3548         }
3549         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3550         if (shaderstring)
3551         {
3552                 if (printfromdisknotice)
3553                         Con_DPrintf("from disk %s... ", filename);
3554                 return shaderstring;
3555         }
3556         return shaderstring;
3557 }
3558
3559 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3560 {
3561         int i;
3562         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3563         int vertstrings_count = 0;
3564         int geomstrings_count = 0;
3565         int fragstrings_count = 0;
3566         char *vertexstring, *geometrystring, *fragmentstring;
3567         const char *vertstrings_list[32+3];
3568         const char *geomstrings_list[32+3];
3569         const char *fragstrings_list[32+3];
3570         char permutationname[256];
3571
3572         if (p->compiled)
3573                 return;
3574         p->compiled = true;
3575         p->program = 0;
3576
3577         permutationname[0] = 0;
3578         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3579         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3580         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3581
3582         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3583
3584         // the first pretext is which type of shader to compile as
3585         // (later these will all be bound together as a program object)
3586         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3587         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3588         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3589
3590         // the second pretext is the mode (for example a light source)
3591         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3592         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3593         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3594         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3595
3596         // now add all the permutation pretexts
3597         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3598         {
3599                 if (permutation & (1<<i))
3600                 {
3601                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3602                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3603                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3604                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3605                 }
3606                 else
3607                 {
3608                         // keep line numbers correct
3609                         vertstrings_list[vertstrings_count++] = "\n";
3610                         geomstrings_list[geomstrings_count++] = "\n";
3611                         fragstrings_list[fragstrings_count++] = "\n";
3612                 }
3613         }
3614
3615         // now append the shader text itself
3616         vertstrings_list[vertstrings_count++] = vertexstring;
3617         geomstrings_list[geomstrings_count++] = geometrystring;
3618         fragstrings_list[fragstrings_count++] = fragmentstring;
3619
3620         // if any sources were NULL, clear the respective list
3621         if (!vertexstring)
3622                 vertstrings_count = 0;
3623         if (!geometrystring)
3624                 geomstrings_count = 0;
3625         if (!fragmentstring)
3626                 fragstrings_count = 0;
3627
3628         // compile the shader program
3629         if (vertstrings_count + geomstrings_count + fragstrings_count)
3630                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3631         if (p->program)
3632         {
3633                 CHECKGLERROR
3634                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3635                 // look up all the uniform variable names we care about, so we don't
3636                 // have to look them up every time we set them
3637
3638                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3639                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3640                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3641                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3642                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3643                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3644                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3645                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3646                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3647                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3648                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3649                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3650                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3651                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3652                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3653                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3654                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3655                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3656                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3657                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3658                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3659                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3660                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3661                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3662                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3663                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3664                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3665                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3666                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3667                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3668                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3669                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3670                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3671                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3672                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3673                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3674                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3675                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3676                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3677                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3678                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3679                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3680                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3681                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3682                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3683                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3684                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3685                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3686                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3687                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3688                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3689                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3690                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3691                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3692                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3693                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3694                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3695                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3696                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3697                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3698                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3699                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3700                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3701                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3702                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3703                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3704                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3705                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3706                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3707                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3708                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3709                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3710                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3711                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3712                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3713                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3714                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3715                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3716                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3717                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3718                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3719                 // initialize the samplers to refer to the texture units we use
3720                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3721                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3722                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3723                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3724                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3725                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3726                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3727                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3728                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3729                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3730                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3731                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3732                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3733                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3734                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3735                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3736                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3737                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3738                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3739                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3740                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3741                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3742                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3743                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3744                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3745                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3746                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3747                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3748                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3749                 CHECKGLERROR
3750                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3751         }
3752         else
3753                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3754
3755         // free the strings
3756         if (vertexstring)
3757                 Mem_Free(vertexstring);
3758         if (geometrystring)
3759                 Mem_Free(geometrystring);
3760         if (fragmentstring)
3761                 Mem_Free(fragmentstring);
3762 }
3763
3764 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3765 {
3766         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3767         if (r_glsl_permutation != perm)
3768         {
3769                 r_glsl_permutation = perm;
3770                 if (!r_glsl_permutation->program)
3771                 {
3772                         if (!r_glsl_permutation->compiled)
3773                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3774                         if (!r_glsl_permutation->program)
3775                         {
3776                                 // remove features until we find a valid permutation
3777                                 int i;
3778                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3779                                 {
3780                                         // reduce i more quickly whenever it would not remove any bits
3781                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3782                                         if (!(permutation & j))
3783                                                 continue;
3784                                         permutation -= j;
3785                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3786                                         if (!r_glsl_permutation->compiled)
3787                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3788                                         if (r_glsl_permutation->program)
3789                                                 break;
3790                                 }
3791                                 if (i >= SHADERPERMUTATION_COUNT)
3792                                 {
3793                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3794                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3795                                         qglUseProgramObjectARB(0);CHECKGLERROR
3796                                         return; // no bit left to clear, entire mode is broken
3797                                 }
3798                         }
3799                 }
3800                 CHECKGLERROR
3801                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3802         }
3803         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3804         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3805         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3806 }
3807
3808 #ifdef SUPPORTCG
3809 #include <Cg/cgGL.h>
3810 struct r_cg_permutation_s;
3811 typedef struct r_cg_permutation_s
3812 {
3813         /// hash lookup data
3814         struct r_cg_permutation_s *hashnext;
3815         unsigned int mode;
3816         unsigned int permutation;
3817
3818         /// indicates if we have tried compiling this permutation already
3819         qboolean compiled;
3820         /// 0 if compilation failed
3821         CGprogram vprogram;
3822         CGprogram fprogram;
3823         /// locations of detected parameters in programs, or NULL if not found
3824         CGparameter vp_EyePosition;
3825         CGparameter vp_FogPlane;
3826         CGparameter vp_LightDir;
3827         CGparameter vp_LightPosition;
3828         CGparameter vp_ModelToLight;
3829         CGparameter vp_TexMatrix;
3830         CGparameter vp_BackgroundTexMatrix;
3831         CGparameter vp_ModelViewProjectionMatrix;
3832         CGparameter vp_ModelViewMatrix;
3833         CGparameter vp_ShadowMapMatrix;
3834
3835         CGparameter fp_Texture_First;
3836         CGparameter fp_Texture_Second;
3837         CGparameter fp_Texture_GammaRamps;
3838         CGparameter fp_Texture_Normal;
3839         CGparameter fp_Texture_Color;
3840         CGparameter fp_Texture_Gloss;
3841         CGparameter fp_Texture_Glow;
3842         CGparameter fp_Texture_SecondaryNormal;
3843         CGparameter fp_Texture_SecondaryColor;
3844         CGparameter fp_Texture_SecondaryGloss;
3845         CGparameter fp_Texture_SecondaryGlow;
3846         CGparameter fp_Texture_Pants;
3847         CGparameter fp_Texture_Shirt;
3848         CGparameter fp_Texture_FogHeightTexture;
3849         CGparameter fp_Texture_FogMask;
3850         CGparameter fp_Texture_Lightmap;
3851         CGparameter fp_Texture_Deluxemap;
3852         CGparameter fp_Texture_Attenuation;
3853         CGparameter fp_Texture_Cube;
3854         CGparameter fp_Texture_Refraction;
3855         CGparameter fp_Texture_Reflection;
3856         CGparameter fp_Texture_ShadowMap2D;
3857         CGparameter fp_Texture_CubeProjection;
3858         CGparameter fp_Texture_ScreenDepth;
3859         CGparameter fp_Texture_ScreenNormalMap;
3860         CGparameter fp_Texture_ScreenDiffuse;
3861         CGparameter fp_Texture_ScreenSpecular;
3862         CGparameter fp_Texture_ReflectMask;
3863         CGparameter fp_Texture_ReflectCube;
3864         CGparameter fp_Alpha;
3865         CGparameter fp_BloomBlur_Parameters;
3866         CGparameter fp_ClientTime;
3867         CGparameter fp_Color_Ambient;
3868         CGparameter fp_Color_Diffuse;
3869         CGparameter fp_Color_Specular;
3870         CGparameter fp_Color_Glow;
3871         CGparameter fp_Color_Pants;
3872         CGparameter fp_Color_Shirt;
3873         CGparameter fp_DeferredColor_Ambient;
3874         CGparameter fp_DeferredColor_Diffuse;
3875         CGparameter fp_DeferredColor_Specular;
3876         CGparameter fp_DeferredMod_Diffuse;
3877         CGparameter fp_DeferredMod_Specular;
3878         CGparameter fp_DistortScaleRefractReflect;
3879         CGparameter fp_EyePosition;
3880         CGparameter fp_FogColor;
3881         CGparameter fp_FogHeightFade;
3882         CGparameter fp_FogPlane;
3883         CGparameter fp_FogPlaneViewDist;
3884         CGparameter fp_FogRangeRecip;
3885         CGparameter fp_LightColor;
3886         CGparameter fp_LightDir;
3887         CGparameter fp_LightPosition;
3888         CGparameter fp_OffsetMapping_Scale;
3889         CGparameter fp_PixelSize;
3890         CGparameter fp_ReflectColor;
3891         CGparameter fp_ReflectFactor;
3892         CGparameter fp_ReflectOffset;
3893         CGparameter fp_RefractColor;
3894         CGparameter fp_Saturation;
3895         CGparameter fp_ScreenCenterRefractReflect;
3896         CGparameter fp_ScreenScaleRefractReflect;
3897         CGparameter fp_ScreenToDepth;
3898         CGparameter fp_ShadowMap_Parameters;
3899         CGparameter fp_ShadowMap_TextureScale;
3900         CGparameter fp_SpecularPower;
3901         CGparameter fp_UserVec1;
3902         CGparameter fp_UserVec2;
3903         CGparameter fp_UserVec3;
3904         CGparameter fp_UserVec4;
3905         CGparameter fp_ViewTintColor;
3906         CGparameter fp_ViewToLight;
3907         CGparameter fp_PixelToScreenTexCoord;
3908         CGparameter fp_ModelToReflectCube;
3909         CGparameter fp_BloomColorSubtract;
3910 }
3911 r_cg_permutation_t;
3912
3913 /// information about each possible shader permutation
3914 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3915 /// currently selected permutation
3916 r_cg_permutation_t *r_cg_permutation;
3917 /// storage for permutations linked in the hash table
3918 memexpandablearray_t r_cg_permutationarray;
3919
3920 #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));}}
3921
3922 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3923 {
3924         //unsigned int hashdepth = 0;
3925         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3926         r_cg_permutation_t *p;
3927         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3928         {
3929                 if (p->mode == mode && p->permutation == permutation)
3930                 {
3931                         //if (hashdepth > 10)
3932                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3933                         return p;
3934                 }
3935                 //hashdepth++;
3936         }
3937         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3938         p->mode = mode;
3939         p->permutation = permutation;
3940         p->hashnext = r_cg_permutationhash[mode][hashindex];
3941         r_cg_permutationhash[mode][hashindex] = p;
3942         //if (hashdepth > 10)
3943         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3944         return p;
3945 }
3946
3947 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3948 {
3949         char *shaderstring;
3950         if (!filename || !filename[0])
3951                 return NULL;
3952         if (!strcmp(filename, "cg/default.cg"))
3953         {
3954                 if (!cgshaderstring)
3955                 {
3956                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3957                         if (cgshaderstring)
3958                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3959                         else
3960                                 cgshaderstring = (char *)builtincgshaderstring;
3961                 }
3962                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3963                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3964                 return shaderstring;
3965         }
3966         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3967         if (shaderstring)
3968         {
3969                 if (printfromdisknotice)
3970                         Con_DPrintf("from disk %s... ", filename);
3971                 return shaderstring;
3972         }
3973         return shaderstring;
3974 }
3975
3976 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3977 {
3978         // TODO: load or create .fp and .vp shader files
3979 }
3980
3981 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3982 {
3983         int i;
3984         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3985         int vertstrings_count = 0, vertstring_length = 0;
3986         int geomstrings_count = 0, geomstring_length = 0;
3987         int fragstrings_count = 0, fragstring_length = 0;
3988         char *t;
3989         char *vertexstring, *geometrystring, *fragmentstring;
3990         char *vertstring, *geomstring, *fragstring;
3991         const char *vertstrings_list[32+3];
3992         const char *geomstrings_list[32+3];
3993         const char *fragstrings_list[32+3];
3994         char permutationname[256];
3995         char cachename[256];
3996         CGprofile vertexProfile;
3997         CGprofile fragmentProfile;
3998
3999         if (p->compiled)
4000                 return;
4001         p->compiled = true;
4002         p->vprogram = NULL;
4003         p->fprogram = NULL;
4004
4005         permutationname[0] = 0;
4006         cachename[0] = 0;
4007         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4008         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4009         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4010
4011         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4012         strlcat(cachename, "cg/", sizeof(cachename));
4013
4014         // the first pretext is which type of shader to compile as
4015         // (later these will all be bound together as a program object)
4016         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4017         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4018         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4019
4020         // the second pretext is the mode (for example a light source)
4021         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4022         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4023         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4024         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4025         strlcat(cachename, modeinfo->name, sizeof(cachename));
4026
4027         // now add all the permutation pretexts
4028         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4029         {
4030                 if (permutation & (1<<i))
4031                 {
4032                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4033                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4034                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4035                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4036                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4037                 }
4038                 else
4039                 {
4040                         // keep line numbers correct
4041                         vertstrings_list[vertstrings_count++] = "\n";
4042                         geomstrings_list[geomstrings_count++] = "\n";
4043                         fragstrings_list[fragstrings_count++] = "\n";
4044                 }
4045         }
4046
4047         // replace spaces in the cachename with _ characters
4048         for (i = 0;cachename[i];i++)
4049                 if (cachename[i] == ' ')
4050                         cachename[i] = '_';
4051
4052         // now append the shader text itself
4053         vertstrings_list[vertstrings_count++] = vertexstring;
4054         geomstrings_list[geomstrings_count++] = geometrystring;
4055         fragstrings_list[fragstrings_count++] = fragmentstring;
4056
4057         // if any sources were NULL, clear the respective list
4058         if (!vertexstring)
4059                 vertstrings_count = 0;
4060         if (!geometrystring)
4061                 geomstrings_count = 0;
4062         if (!fragmentstring)
4063                 fragstrings_count = 0;
4064
4065         vertstring_length = 0;
4066         for (i = 0;i < vertstrings_count;i++)
4067                 vertstring_length += strlen(vertstrings_list[i]);
4068         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4069         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4070                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4071
4072         geomstring_length = 0;
4073         for (i = 0;i < geomstrings_count;i++)
4074                 geomstring_length += strlen(geomstrings_list[i]);
4075         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4076         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4077                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4078
4079         fragstring_length = 0;
4080         for (i = 0;i < fragstrings_count;i++)
4081                 fragstring_length += strlen(fragstrings_list[i]);
4082         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4083         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4084                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4085
4086         CHECKGLERROR
4087         CHECKCGERROR
4088         //vertexProfile = CG_PROFILE_ARBVP1;
4089         //fragmentProfile = CG_PROFILE_ARBFP1;
4090         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4091         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4092         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4093         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4094         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4095         CHECKGLERROR
4096
4097         // try to load the cached shader, or generate one
4098         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4099
4100         // if caching failed, do a dynamic compile for now
4101         CHECKCGERROR
4102         if (vertstring[0] && !p->vprogram)
4103                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4104         CHECKCGERROR
4105         if (fragstring[0] && !p->fprogram)
4106                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4107         CHECKCGERROR
4108
4109         // look up all the uniform variable names we care about, so we don't
4110         // have to look them up every time we set them
4111         if (p->vprogram)
4112         {
4113                 CHECKCGERROR
4114                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4115                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4116                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4117                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4118                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4119                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4120                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4121                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4122                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4123                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4124                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4125                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4126                 CHECKCGERROR
4127         }
4128         if (p->fprogram)
4129         {
4130                 CHECKCGERROR
4131                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4132                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4133                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4134                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4135                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4136                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4137                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4138                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4139                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4140                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4141                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4142                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4143                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4144                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4145                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4146                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4147                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4148                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4149                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4150                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4151                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4152                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4153                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4154                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4155                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4156                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4157                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4158                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4159                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4160                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4161                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4162                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4163                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4164                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4165                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4166                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4167                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4168                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4169                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4170                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4171                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4172                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4173                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4174                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4175                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4176                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4177                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4178                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4179                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4180                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4181                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4182                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4183                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4184                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4185                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4186                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4187                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4188                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4189                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4190                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4191                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4192                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4193                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4194                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4195                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4196                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4197                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4198                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4199                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4200                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4201                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4202                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4203                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4204                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4205                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4206                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4207                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4208                 CHECKCGERROR
4209         }
4210
4211         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4212                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4213         else
4214                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4215
4216         // free the strings
4217         if (vertstring)
4218                 Mem_Free(vertstring);
4219         if (geomstring)
4220                 Mem_Free(geomstring);
4221         if (fragstring)
4222                 Mem_Free(fragstring);
4223         if (vertexstring)
4224                 Mem_Free(vertexstring);
4225         if (geometrystring)
4226                 Mem_Free(geometrystring);
4227         if (fragmentstring)
4228                 Mem_Free(fragmentstring);
4229 }
4230
4231 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4232 {
4233         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4234         CHECKGLERROR
4235         CHECKCGERROR
4236         if (r_cg_permutation != perm)
4237         {
4238                 r_cg_permutation = perm;
4239                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4240                 {
4241                         if (!r_cg_permutation->compiled)
4242                                 R_CG_CompilePermutation(perm, mode, permutation);
4243                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4244                         {
4245                                 // remove features until we find a valid permutation
4246                                 int i;
4247                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4248                                 {
4249                                         // reduce i more quickly whenever it would not remove any bits
4250                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4251                                         if (!(permutation & j))
4252                                                 continue;
4253                                         permutation -= j;
4254                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4255                                         if (!r_cg_permutation->compiled)
4256                                                 R_CG_CompilePermutation(perm, mode, permutation);
4257                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4258                                                 break;
4259                                 }
4260                                 if (i >= SHADERPERMUTATION_COUNT)
4261                                 {
4262                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4263                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4264                                         return; // no bit left to clear, entire mode is broken
4265                                 }
4266                         }
4267                 }
4268                 CHECKGLERROR
4269                 CHECKCGERROR
4270                 if (r_cg_permutation->vprogram)
4271                 {
4272                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4273                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4274                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4275                 }
4276                 else
4277                 {
4278                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4279                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4280                 }
4281                 if (r_cg_permutation->fprogram)
4282                 {
4283                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4284                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4285                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4286                 }
4287                 else
4288                 {
4289                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4290                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4291                 }
4292         }
4293         CHECKCGERROR
4294         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4295         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4296         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4297 }
4298
4299 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4300 {
4301         cgGLSetTextureParameter(param, R_GetTexture(tex));
4302         cgGLEnableTextureParameter(param);
4303 }
4304 #endif
4305
4306 #ifdef SUPPORTD3D
4307
4308 #ifdef SUPPORTD3D
4309 #include <d3d9.h>
4310 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4311 extern D3DCAPS9 vid_d3d9caps;
4312 #endif
4313
4314 struct r_hlsl_permutation_s;
4315 typedef struct r_hlsl_permutation_s
4316 {
4317         /// hash lookup data
4318         struct r_hlsl_permutation_s *hashnext;
4319         unsigned int mode;
4320         unsigned int permutation;
4321
4322         /// indicates if we have tried compiling this permutation already
4323         qboolean compiled;
4324         /// NULL if compilation failed
4325         IDirect3DVertexShader9 *vertexshader;
4326         IDirect3DPixelShader9 *pixelshader;
4327 }
4328 r_hlsl_permutation_t;
4329
4330 typedef enum D3DVSREGISTER_e
4331 {
4332         D3DVSREGISTER_TexMatrix = 0, // float4x4
4333         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4334         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4335         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4336         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4337         D3DVSREGISTER_ModelToLight = 20, // float4x4
4338         D3DVSREGISTER_EyePosition = 24,
4339         D3DVSREGISTER_FogPlane = 25,
4340         D3DVSREGISTER_LightDir = 26,
4341         D3DVSREGISTER_LightPosition = 27,
4342 }
4343 D3DVSREGISTER_t;
4344
4345 typedef enum D3DPSREGISTER_e
4346 {
4347         D3DPSREGISTER_Alpha = 0,
4348         D3DPSREGISTER_BloomBlur_Parameters = 1,
4349         D3DPSREGISTER_ClientTime = 2,
4350         D3DPSREGISTER_Color_Ambient = 3,
4351         D3DPSREGISTER_Color_Diffuse = 4,
4352         D3DPSREGISTER_Color_Specular = 5,
4353         D3DPSREGISTER_Color_Glow = 6,
4354         D3DPSREGISTER_Color_Pants = 7,
4355         D3DPSREGISTER_Color_Shirt = 8,
4356         D3DPSREGISTER_DeferredColor_Ambient = 9,
4357         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4358         D3DPSREGISTER_DeferredColor_Specular = 11,
4359         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4360         D3DPSREGISTER_DeferredMod_Specular = 13,
4361         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4362         D3DPSREGISTER_EyePosition = 15, // unused
4363         D3DPSREGISTER_FogColor = 16,
4364         D3DPSREGISTER_FogHeightFade = 17,
4365         D3DPSREGISTER_FogPlane = 18,
4366         D3DPSREGISTER_FogPlaneViewDist = 19,
4367         D3DPSREGISTER_FogRangeRecip = 20,
4368         D3DPSREGISTER_LightColor = 21,
4369         D3DPSREGISTER_LightDir = 22, // unused
4370         D3DPSREGISTER_LightPosition = 23,
4371         D3DPSREGISTER_OffsetMapping_Scale = 24,
4372         D3DPSREGISTER_PixelSize = 25,
4373         D3DPSREGISTER_ReflectColor = 26,
4374         D3DPSREGISTER_ReflectFactor = 27,
4375         D3DPSREGISTER_ReflectOffset = 28,
4376         D3DPSREGISTER_RefractColor = 29,
4377         D3DPSREGISTER_Saturation = 30,
4378         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4379         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4380         D3DPSREGISTER_ScreenToDepth = 33,
4381         D3DPSREGISTER_ShadowMap_Parameters = 34,
4382         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4383         D3DPSREGISTER_SpecularPower = 36,
4384         D3DPSREGISTER_UserVec1 = 37,
4385         D3DPSREGISTER_UserVec2 = 38,
4386         D3DPSREGISTER_UserVec3 = 39,
4387         D3DPSREGISTER_UserVec4 = 40,
4388         D3DPSREGISTER_ViewTintColor = 41,
4389         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4390         D3DPSREGISTER_BloomColorSubtract = 43,
4391         D3DPSREGISTER_ViewToLight = 44, // float4x4
4392         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4393         // next at 52
4394 }
4395 D3DPSREGISTER_t;
4396
4397 /// information about each possible shader permutation
4398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4399 /// currently selected permutation
4400 r_hlsl_permutation_t *r_hlsl_permutation;
4401 /// storage for permutations linked in the hash table
4402 memexpandablearray_t r_hlsl_permutationarray;
4403
4404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4405 {
4406         //unsigned int hashdepth = 0;
4407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4408         r_hlsl_permutation_t *p;
4409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4410         {
4411                 if (p->mode == mode && p->permutation == permutation)
4412                 {
4413                         //if (hashdepth > 10)
4414                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4415                         return p;
4416                 }
4417                 //hashdepth++;
4418         }
4419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4420         p->mode = mode;
4421         p->permutation = permutation;
4422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4423         r_hlsl_permutationhash[mode][hashindex] = p;
4424         //if (hashdepth > 10)
4425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4426         return p;
4427 }
4428
4429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4430 {
4431         char *shaderstring;
4432         if (!filename || !filename[0])
4433                 return NULL;
4434         if (!strcmp(filename, "hlsl/default.hlsl"))
4435         {
4436                 if (!hlslshaderstring)
4437                 {
4438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4439                         if (hlslshaderstring)
4440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4441                         else
4442                                 hlslshaderstring = (char *)builtincgshaderstring;
4443                 }
4444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4446                 return shaderstring;
4447         }
4448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4449         if (shaderstring)
4450         {
4451                 if (printfromdisknotice)
4452                         Con_DPrintf("from disk %s... ", filename);
4453                 return shaderstring;
4454         }
4455         return shaderstring;
4456 }
4457
4458 #include <d3dx9.h>
4459 //#include <d3dx9shader.h>
4460 //#include <d3dx9mesh.h>
4461
4462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4463 {
4464         DWORD *vsbin = NULL;
4465         DWORD *psbin = NULL;
4466         fs_offset_t vsbinsize;
4467         fs_offset_t psbinsize;
4468 //      IDirect3DVertexShader9 *vs = NULL;
4469 //      IDirect3DPixelShader9 *ps = NULL;
4470         ID3DXBuffer *vslog = NULL;
4471         ID3DXBuffer *vsbuffer = NULL;
4472         ID3DXConstantTable *vsconstanttable = NULL;
4473         ID3DXBuffer *pslog = NULL;
4474         ID3DXBuffer *psbuffer = NULL;
4475         ID3DXConstantTable *psconstanttable = NULL;
4476         int vsresult = 0;
4477         int psresult = 0;
4478         char temp[MAX_INPUTLINE];
4479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4480         qboolean debugshader = gl_paranoid.integer != 0;
4481         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4483         if (!debugshader)
4484         {
4485                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4486                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4487         }
4488         if (debugshader || (!vsbin && vertstring) || (!psbin && fragstring))
4489         {
4490                 const char* dllnames_d3dx9 [] =
4491                 {
4492                         "d3dx9_43.dll",
4493                         "d3dx9_42.dll",
4494                         "d3dx9_41.dll",
4495                         "d3dx9_40.dll",
4496                         "d3dx9_39.dll",
4497                         "d3dx9_38.dll",
4498                         "d3dx9_37.dll",
4499                         "d3dx9_36.dll",
4500                         "d3dx9_35.dll",
4501                         "d3dx9_34.dll",
4502                         "d3dx9_33.dll",
4503                         "d3dx9_32.dll",
4504                         "d3dx9_31.dll",
4505                         "d3dx9_30.dll",
4506                         "d3dx9_29.dll",
4507                         "d3dx9_28.dll",
4508                         "d3dx9_27.dll",
4509                         "d3dx9_26.dll",
4510                         "d3dx9_25.dll",
4511                         "d3dx9_24.dll",
4512                         NULL
4513                 };
4514                 dllhandle_t d3dx9_dll = NULL;
4515                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4516                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4517                 dllfunction_t d3dx9_dllfuncs[] =
4518                 {
4519                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4520                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4521                         {NULL, NULL}
4522                 };
4523                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4524                 {
4525                         DWORD shaderflags = 0;
4526                         if (debugshader)
4527                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4528                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4529                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4530                         if (vertstring && vertstring[0])
4531                         {
4532                                 if (debugshader)
4533                                 {
4534                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4535                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4536                                 }
4537                                 else
4538                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4539                                 if (vsbuffer)
4540                                 {
4541                                         vsbinsize = vsbuffer->GetBufferSize();
4542                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4543                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4544                                         vsbuffer->Release();
4545                                 }
4546                                 if (vslog)
4547                                 {
4548                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4549                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4550                                         vslog->Release();
4551                                 }
4552                         }
4553                         if (fragstring && fragstring[0])
4554                         {
4555                                 if (debugshader)
4556                                 {
4557                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4558                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4559                                 }
4560                                 else
4561                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4562                                 if (psbuffer)
4563                                 {
4564                                         psbinsize = psbuffer->GetBufferSize();
4565                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4566                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4567                                         psbuffer->Release();
4568                                 }
4569                                 if (pslog)
4570                                 {
4571                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4572                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4573                                         pslog->Release();
4574                                 }
4575                         }
4576                         Sys_UnloadLibrary(&d3dx9_dll);
4577                 }
4578                 else
4579                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4580         }
4581         if (vsbin)
4582         {
4583                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4584                 if (FAILED(vsresult))
4585                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4586         }
4587         if (psbin)
4588         {
4589                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4590                 if (FAILED(psresult))
4591                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4592         }
4593         // free the shader data
4594         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4595         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4596 }
4597
4598 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4599 {
4600         int i;
4601         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4602         int vertstrings_count = 0, vertstring_length = 0;
4603         int geomstrings_count = 0, geomstring_length = 0;
4604         int fragstrings_count = 0, fragstring_length = 0;
4605         char *t;
4606         char *vertexstring, *geometrystring, *fragmentstring;
4607         char *vertstring, *geomstring, *fragstring;
4608         const char *vertstrings_list[32+3];
4609         const char *geomstrings_list[32+3];
4610         const char *fragstrings_list[32+3];
4611         char permutationname[256];
4612         char cachename[256];
4613
4614         if (p->compiled)
4615                 return;
4616         p->compiled = true;
4617         p->vertexshader = NULL;
4618         p->pixelshader = NULL;
4619
4620         permutationname[0] = 0;
4621         cachename[0] = 0;
4622         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4623         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4624         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4625
4626         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4627         strlcat(cachename, "hlsl/", sizeof(cachename));
4628
4629         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4630         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4631         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4632         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4633
4634         // the first pretext is which type of shader to compile as
4635         // (later these will all be bound together as a program object)
4636         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4637         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4638         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4639
4640         // the second pretext is the mode (for example a light source)
4641         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4642         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4643         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4644         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4645         strlcat(cachename, modeinfo->name, sizeof(cachename));
4646
4647         // now add all the permutation pretexts
4648         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4649         {
4650                 if (permutation & (1<<i))
4651                 {
4652                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4653                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4654                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4655                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4656                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4657                 }
4658                 else
4659                 {
4660                         // keep line numbers correct
4661                         vertstrings_list[vertstrings_count++] = "\n";
4662                         geomstrings_list[geomstrings_count++] = "\n";
4663                         fragstrings_list[fragstrings_count++] = "\n";
4664                 }
4665         }
4666
4667         // replace spaces in the cachename with _ characters
4668         for (i = 0;cachename[i];i++)
4669                 if (cachename[i] == ' ')
4670                         cachename[i] = '_';
4671
4672         // now append the shader text itself
4673         vertstrings_list[vertstrings_count++] = vertexstring;
4674         geomstrings_list[geomstrings_count++] = geometrystring;
4675         fragstrings_list[fragstrings_count++] = fragmentstring;
4676
4677         // if any sources were NULL, clear the respective list
4678         if (!vertexstring)
4679                 vertstrings_count = 0;
4680         if (!geometrystring)
4681                 geomstrings_count = 0;
4682         if (!fragmentstring)
4683                 fragstrings_count = 0;
4684
4685         vertstring_length = 0;
4686         for (i = 0;i < vertstrings_count;i++)
4687                 vertstring_length += strlen(vertstrings_list[i]);
4688         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4689         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4690                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4691
4692         geomstring_length = 0;
4693         for (i = 0;i < geomstrings_count;i++)
4694                 geomstring_length += strlen(geomstrings_list[i]);
4695         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4696         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4697                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4698
4699         fragstring_length = 0;
4700         for (i = 0;i < fragstrings_count;i++)
4701                 fragstring_length += strlen(fragstrings_list[i]);
4702         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4703         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4704                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4705
4706         // try to load the cached shader, or generate one
4707         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4708
4709         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4710                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4711         else
4712                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4713
4714         // free the strings
4715         if (vertstring)
4716                 Mem_Free(vertstring);
4717         if (geomstring)
4718                 Mem_Free(geomstring);
4719         if (fragstring)
4720                 Mem_Free(fragstring);
4721         if (vertexstring)
4722                 Mem_Free(vertexstring);
4723         if (geometrystring)
4724                 Mem_Free(geometrystring);
4725         if (fragmentstring)
4726                 Mem_Free(fragmentstring);
4727 }
4728
4729 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4730 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4731 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);}
4732 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);}
4733 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);}
4734 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);}
4735
4736 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4737 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4738 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);}
4739 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);}
4740 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);}
4741 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);}
4742
4743 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4744 {
4745         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4746         if (r_hlsl_permutation != perm)
4747         {
4748                 r_hlsl_permutation = perm;
4749                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4750                 {
4751                         if (!r_hlsl_permutation->compiled)
4752                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4753                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4754                         {
4755                                 // remove features until we find a valid permutation
4756                                 int i;
4757                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4758                                 {
4759                                         // reduce i more quickly whenever it would not remove any bits
4760                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4761                                         if (!(permutation & j))
4762                                                 continue;
4763                                         permutation -= j;
4764                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4765                                         if (!r_hlsl_permutation->compiled)
4766                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4767                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4768                                                 break;
4769                                 }
4770                                 if (i >= SHADERPERMUTATION_COUNT)
4771                                 {
4772                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4773                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4774                                         return; // no bit left to clear, entire mode is broken
4775                                 }
4776                         }
4777                 }
4778                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4779                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4780         }
4781         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4782         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4783         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4784 }
4785 #endif
4786
4787 void R_GLSL_Restart_f(void)
4788 {
4789         unsigned int i, limit;
4790         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4791                 Mem_Free(glslshaderstring);
4792         glslshaderstring = NULL;
4793         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4794                 Mem_Free(cgshaderstring);
4795         cgshaderstring = NULL;
4796         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4797                 Mem_Free(hlslshaderstring);
4798         hlslshaderstring = NULL;
4799         switch(vid.renderpath)
4800         {
4801         case RENDERPATH_D3D9:
4802 #ifdef SUPPORTD3D
4803                 {
4804                         r_hlsl_permutation_t *p;
4805                         r_hlsl_permutation = NULL;
4806 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4807 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4808 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4809 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4810                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4811                         for (i = 0;i < limit;i++)
4812                         {
4813                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4814                                 {
4815                                         if (p->vertexshader)
4816                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4817                                         if (p->pixelshader)
4818                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4819                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4820                                 }
4821                         }
4822                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4823                 }
4824 #endif
4825                 break;
4826         case RENDERPATH_D3D10:
4827                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4828                 break;
4829         case RENDERPATH_D3D11:
4830                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4831                 break;
4832         case RENDERPATH_GL20:
4833                 {
4834                         r_glsl_permutation_t *p;
4835                         r_glsl_permutation = NULL;
4836                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4837                         for (i = 0;i < limit;i++)
4838                         {
4839                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4840                                 {
4841                                         GL_Backend_FreeProgram(p->program);
4842                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4843                                 }
4844                         }
4845                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4846                 }
4847                 break;
4848         case RENDERPATH_CGGL:
4849 #ifdef SUPPORTCG
4850                 {
4851                         r_cg_permutation_t *p;
4852                         r_cg_permutation = NULL;
4853                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4854                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4855                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4856                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4857                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4858                         for (i = 0;i < limit;i++)
4859                         {
4860                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4861                                 {
4862                                         if (p->vprogram)
4863                                                 cgDestroyProgram(p->vprogram);
4864                                         if (p->fprogram)
4865                                                 cgDestroyProgram(p->fprogram);
4866                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4867                                 }
4868                         }
4869                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4870                 }
4871 #endif
4872                 break;
4873         case RENDERPATH_GL13:
4874         case RENDERPATH_GL11:
4875                 break;
4876         }
4877 }
4878
4879 void R_GLSL_DumpShader_f(void)
4880 {
4881         int i;
4882         qfile_t *file;
4883
4884         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4885         if (file)
4886         {
4887                 FS_Print(file, "/* The engine may define the following macros:\n");
4888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4889                 for (i = 0;i < SHADERMODE_COUNT;i++)
4890                         FS_Print(file, glslshadermodeinfo[i].pretext);
4891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4892                         FS_Print(file, shaderpermutationinfo[i].pretext);
4893                 FS_Print(file, "*/\n");
4894                 FS_Print(file, builtinshaderstring);
4895                 FS_Close(file);
4896                 Con_Printf("glsl/default.glsl written\n");
4897         }
4898         else
4899                 Con_Printf("failed to write to glsl/default.glsl\n");
4900
4901 #ifdef SUPPORTCG
4902         file = FS_OpenRealFile("cg/default.cg", "w", false);
4903         if (file)
4904         {
4905                 FS_Print(file, "/* The engine may define the following macros:\n");
4906                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4907                 for (i = 0;i < SHADERMODE_COUNT;i++)
4908                         FS_Print(file, cgshadermodeinfo[i].pretext);
4909                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4910                         FS_Print(file, shaderpermutationinfo[i].pretext);
4911                 FS_Print(file, "*/\n");
4912                 FS_Print(file, builtincgshaderstring);
4913                 FS_Close(file);
4914                 Con_Printf("cg/default.cg written\n");
4915         }
4916         else
4917                 Con_Printf("failed to write to cg/default.cg\n");
4918 #endif
4919
4920 #ifdef SUPPORTD3D
4921         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4922         if (file)
4923         {
4924                 FS_Print(file, "/* The engine may define the following macros:\n");
4925                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4926                 for (i = 0;i < SHADERMODE_COUNT;i++)
4927                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4928                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4929                         FS_Print(file, shaderpermutationinfo[i].pretext);
4930                 FS_Print(file, "*/\n");
4931                 FS_Print(file, builtincgshaderstring);
4932                 FS_Close(file);
4933                 Con_Printf("hlsl/default.hlsl written\n");
4934         }
4935         else
4936                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4937 #endif
4938 }
4939
4940 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4941 {
4942         if (!second)
4943                 texturemode = GL_MODULATE;
4944         switch (vid.renderpath)
4945         {
4946         case RENDERPATH_D3D9:
4947 #ifdef SUPPORTD3D
4948                 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))));
4949                 R_Mesh_TexBind(GL20TU_FIRST , first );
4950                 R_Mesh_TexBind(GL20TU_SECOND, second);
4951 #endif
4952                 break;
4953         case RENDERPATH_D3D10:
4954                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4955                 break;
4956         case RENDERPATH_D3D11:
4957                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4958                 break;
4959         case RENDERPATH_GL20:
4960                 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))));
4961                 R_Mesh_TexBind(GL20TU_FIRST , first );
4962                 R_Mesh_TexBind(GL20TU_SECOND, second);
4963                 break;
4964         case RENDERPATH_CGGL:
4965 #ifdef SUPPORTCG
4966                 CHECKCGERROR
4967                 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))));
4968                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4969                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4970 #endif
4971                 break;
4972         case RENDERPATH_GL13:
4973                 R_Mesh_TexBind(0, first );
4974                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4975                 R_Mesh_TexBind(1, second);
4976                 if (second)
4977                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4978                 break;
4979         case RENDERPATH_GL11:
4980                 R_Mesh_TexBind(0, first );
4981                 break;
4982         }
4983 }
4984
4985 void R_SetupShader_DepthOrShadow(void)
4986 {
4987         switch (vid.renderpath)
4988         {
4989         case RENDERPATH_D3D9:
4990 #ifdef SUPPORTD3D
4991                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4992 #endif
4993                 break;
4994         case RENDERPATH_D3D10:
4995                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4996                 break;
4997         case RENDERPATH_D3D11:
4998                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4999                 break;
5000         case RENDERPATH_GL20:
5001                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5002                 break;
5003         case RENDERPATH_CGGL:
5004 #ifdef SUPPORTCG
5005                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5006 #endif
5007                 break;
5008         case RENDERPATH_GL13:
5009                 R_Mesh_TexBind(0, 0);
5010                 R_Mesh_TexBind(1, 0);
5011                 break;
5012         case RENDERPATH_GL11:
5013                 R_Mesh_TexBind(0, 0);
5014                 break;
5015         }
5016 }
5017
5018 void R_SetupShader_ShowDepth(void)
5019 {
5020         switch (vid.renderpath)
5021         {
5022         case RENDERPATH_D3D9:
5023 #ifdef SUPPORTHLSL
5024                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5025 #endif
5026                 break;
5027         case RENDERPATH_D3D10:
5028                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5029                 break;
5030         case RENDERPATH_D3D11:
5031                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5032                 break;
5033         case RENDERPATH_GL20:
5034                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5035                 break;
5036         case RENDERPATH_CGGL:
5037 #ifdef SUPPORTCG
5038                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5039 #endif
5040                 break;
5041         case RENDERPATH_GL13:
5042                 break;
5043         case RENDERPATH_GL11:
5044                 break;
5045         }
5046 }
5047
5048 extern qboolean r_shadow_usingdeferredprepass;
5049 extern cvar_t r_shadow_deferred_8bitrange;
5050 extern rtexture_t *r_shadow_attenuationgradienttexture;
5051 extern rtexture_t *r_shadow_attenuation2dtexture;
5052 extern rtexture_t *r_shadow_attenuation3dtexture;
5053 extern qboolean r_shadow_usingshadowmap2d;
5054 extern qboolean r_shadow_usingshadowmaportho;
5055 extern float r_shadow_shadowmap_texturescale[2];
5056 extern float r_shadow_shadowmap_parameters[4];
5057 extern qboolean r_shadow_shadowmapvsdct;
5058 extern qboolean r_shadow_shadowmapsampler;
5059 extern int r_shadow_shadowmappcf;
5060 extern rtexture_t *r_shadow_shadowmap2dtexture;
5061 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5062 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5063 extern matrix4x4_t r_shadow_shadowmapmatrix;
5064 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5065 extern int r_shadow_prepass_width;
5066 extern int r_shadow_prepass_height;
5067 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5068 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5069 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5070 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5071 extern cvar_t gl_mesh_separatearrays;
5072 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5073 {
5074         // a blendfunc allows colormod if:
5075         // a) it can never keep the destination pixel invariant, or
5076         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5077         // this is to prevent unintended side effects from colormod
5078
5079         // in formulas:
5080         // IF there is a (s, sa) for which for all (d, da),
5081         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5082         // THEN, for this (s, sa) and all (colormod, d, da):
5083         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5084         // OBVIOUSLY, this means that
5085         //   s*colormod * src(s*colormod, d, sa, da) = 0
5086         //   dst(s*colormod, d, sa, da)              = 1
5087
5088         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5089
5090         // main condition to leave dst color invariant:
5091         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5092         //   src == GL_ZERO:
5093         //     s * 0 + d * dst(s, d, sa, da) == d
5094         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5095         //       => colormod is a problem for GL_SRC_COLOR only
5096         //   src == GL_ONE:
5097         //     s + d * dst(s, d, sa, da) == d
5098         //       => s == 0
5099         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5100         //       => colormod is never problematic for these
5101         //   src == GL_SRC_COLOR:
5102         //     s*s + d * dst(s, d, sa, da) == d
5103         //       => s == 0
5104         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5105         //       => colormod is never problematic for these
5106         //   src == GL_ONE_MINUS_SRC_COLOR:
5107         //     s*(1-s) + d * dst(s, d, sa, da) == d
5108         //       => s == 0 or s == 1
5109         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5110         //       => colormod is a problem for GL_SRC_COLOR only
5111         //   src == GL_DST_COLOR
5112         //     s*d + d * dst(s, d, sa, da) == d
5113         //       => s == 1
5114         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5115         //       => colormod is always a problem
5116         //     or
5117         //       => s == 0
5118         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5119         //       => colormod is never problematic for these
5120         //       => BUT, we do not know s! We must assume it is problematic
5121         //       then... except in GL_ONE case, where we know all invariant
5122         //       cases are fine
5123         //   src == GL_ONE_MINUS_DST_COLOR
5124         //     s*(1-d) + d * dst(s, d, sa, da) == d
5125         //       => s == 0 (1-d is impossible to handle for our desired result)
5126         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5127         //       => colormod is never problematic for these
5128         //   src == GL_SRC_ALPHA
5129         //     s*sa + d * dst(s, d, sa, da) == d
5130         //       => s == 0, or sa == 0
5131         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5132         //       => colormod breaks in the case GL_SRC_COLOR only
5133         //   src == GL_ONE_MINUS_SRC_ALPHA
5134         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5135         //       => s == 0, or sa == 1
5136         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5137         //       => colormod breaks in the case GL_SRC_COLOR only
5138         //   src == GL_DST_ALPHA
5139         //     s*da + d * dst(s, d, sa, da) == d
5140         //       => s == 0
5141         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5142         //       => colormod is never problematic for these
5143
5144         switch(src)
5145         {
5146                 case GL_ZERO:
5147                 case GL_ONE_MINUS_SRC_COLOR:
5148                 case GL_SRC_ALPHA:
5149                 case GL_ONE_MINUS_SRC_ALPHA:
5150                         if(dst == GL_SRC_COLOR)
5151                                 return false;
5152                         return true;
5153                 case GL_ONE:
5154                 case GL_SRC_COLOR:
5155                 case GL_ONE_MINUS_DST_COLOR:
5156                 case GL_DST_ALPHA:
5157                 case GL_ONE_MINUS_DST_ALPHA:
5158                         return true;
5159                 case GL_DST_COLOR:
5160                         if(dst == GL_ONE)
5161                                 return true;
5162                         return false;
5163                 default:
5164                         return false;
5165         }
5166 }
5167 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)
5168 {
5169         // select a permutation of the lighting shader appropriate to this
5170         // combination of texture, entity, light source, and fogging, only use the
5171         // minimum features necessary to avoid wasting rendering time in the
5172         // fragment shader on features that are not being used
5173         unsigned int permutation = 0;
5174         unsigned int mode = 0;
5175         qboolean allow_colormod;
5176         static float dummy_colormod[3] = {1, 1, 1};
5177         float *colormod = rsurface.colormod;
5178         float m16f[16];
5179         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5180         if (rsurfacepass == RSURFPASS_BACKGROUND)
5181         {
5182                 // distorted background
5183                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5184                         mode = SHADERMODE_WATER;
5185                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5186                         mode = SHADERMODE_REFRACTION;
5187                 else
5188                 {
5189                         mode = SHADERMODE_GENERIC;
5190                         permutation |= SHADERPERMUTATION_DIFFUSE;
5191                 }
5192                 GL_AlphaTest(false);
5193                 GL_BlendFunc(GL_ONE, GL_ZERO);
5194                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5195         }
5196         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5197         {
5198                 if (r_glsl_offsetmapping.integer)
5199                 {
5200                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5201                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5202                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5203                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5204                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5205                         {
5206                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5207                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5208                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5209                         }
5210                 }
5211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5212                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5214                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5215                 // normalmap (deferred prepass), may use alpha test on diffuse
5216                 mode = SHADERMODE_DEFERREDGEOMETRY;
5217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5218                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5219                 GL_AlphaTest(false);
5220                 GL_BlendFunc(GL_ONE, GL_ZERO);
5221                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5222         }
5223         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5224         {
5225                 if (r_glsl_offsetmapping.integer)
5226                 {
5227                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5228                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5229                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5230                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5231                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5232                         {
5233                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5234                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5235                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5236                         }
5237                 }
5238                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5239                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5240                 // light source
5241                 mode = SHADERMODE_LIGHTSOURCE;
5242                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5243                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5244                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5245                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5246                 if (diffusescale > 0)
5247                         permutation |= SHADERPERMUTATION_DIFFUSE;
5248                 if (specularscale > 0)
5249                 {
5250                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5251                         if (r_shadow_glossexact.integer)
5252                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5253                 }
5254                 if (r_refdef.fogenabled)
5255                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5256                 if (rsurface.texture->colormapping)
5257                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5258                 if (r_shadow_usingshadowmap2d)
5259                 {
5260                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5261                         if(r_shadow_shadowmapvsdct)
5262                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5263
5264                         if (r_shadow_shadowmapsampler)
5265                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5266                         if (r_shadow_shadowmappcf > 1)
5267                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5268                         else if (r_shadow_shadowmappcf)
5269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5270                 }
5271                 if (rsurface.texture->reflectmasktexture)
5272                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5273                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5274                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5275                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5276         }
5277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5278         {
5279                 if (r_glsl_offsetmapping.integer)
5280                 {
5281                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5282                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5283                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5284                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5285                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5286                         {
5287                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5288                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5289                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5290                         }
5291                 }
5292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5293                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5294                 // unshaded geometry (fullbright or ambient model lighting)
5295                 mode = SHADERMODE_FLATCOLOR;
5296                 ambientscale = diffusescale = specularscale = 0;
5297                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5298                         permutation |= SHADERPERMUTATION_GLOW;
5299                 if (r_refdef.fogenabled)
5300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5301                 if (rsurface.texture->colormapping)
5302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5304                 {
5305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5307
5308                         if (r_shadow_shadowmapsampler)
5309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5310                         if (r_shadow_shadowmappcf > 1)
5311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5312                         else if (r_shadow_shadowmappcf)
5313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5314                 }
5315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5316                         permutation |= SHADERPERMUTATION_REFLECTION;
5317                 if (rsurface.texture->reflectmasktexture)
5318                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5319                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5320                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5321                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5322         }
5323         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5324         {
5325                 if (r_glsl_offsetmapping.integer)
5326                 {
5327                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5328                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5329                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5330                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5331                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5332                         {
5333                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5334                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5335                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5336                         }
5337                 }
5338                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5339                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5340                 // directional model lighting
5341                 mode = SHADERMODE_LIGHTDIRECTION;
5342                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5343                         permutation |= SHADERPERMUTATION_GLOW;
5344                 permutation |= SHADERPERMUTATION_DIFFUSE;
5345                 if (specularscale > 0)
5346                 {
5347                         permutation |= SHADERPERMUTATION_SPECULAR;
5348                         if (r_shadow_glossexact.integer)
5349                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5350                 }
5351                 if (r_refdef.fogenabled)
5352                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5353                 if (rsurface.texture->colormapping)
5354                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5355                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5356                 {
5357                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5358                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5359
5360                         if (r_shadow_shadowmapsampler)
5361                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5362                         if (r_shadow_shadowmappcf > 1)
5363                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5364                         else if (r_shadow_shadowmappcf)
5365                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5366                 }
5367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5368                         permutation |= SHADERPERMUTATION_REFLECTION;
5369                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5370                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5371                 if (rsurface.texture->reflectmasktexture)
5372                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5373                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5374                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5375                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5376         }
5377         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5378         {
5379                 if (r_glsl_offsetmapping.integer)
5380                 {
5381                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5382                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5383                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5384                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5385                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5386                         {
5387                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5388                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5389                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5390                         }
5391                 }
5392                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5393                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5394                 // ambient model lighting
5395                 mode = SHADERMODE_LIGHTDIRECTION;
5396                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5397                         permutation |= SHADERPERMUTATION_GLOW;
5398                 if (r_refdef.fogenabled)
5399                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5400                 if (rsurface.texture->colormapping)
5401                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5402                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5403                 {
5404                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5405                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5406
5407                         if (r_shadow_shadowmapsampler)
5408                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5409                         if (r_shadow_shadowmappcf > 1)
5410                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5411                         else if (r_shadow_shadowmappcf)
5412                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5413                 }
5414                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5415                         permutation |= SHADERPERMUTATION_REFLECTION;
5416                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5417                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5418                 if (rsurface.texture->reflectmasktexture)
5419                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5420                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5421                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5422                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5423         }
5424         else
5425         {
5426                 if (r_glsl_offsetmapping.integer)
5427                 {
5428                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5429                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5430                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5431                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5432                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5433                         {
5434                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5435                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5436                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5437                         }
5438                 }
5439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5441                 // lightmapped wall
5442                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5443                         permutation |= SHADERPERMUTATION_GLOW;
5444                 if (r_refdef.fogenabled)
5445                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5446                 if (rsurface.texture->colormapping)
5447                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5448                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5449                 {
5450                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5451                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5452
5453                         if (r_shadow_shadowmapsampler)
5454                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5455                         if (r_shadow_shadowmappcf > 1)
5456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5457                         else if (r_shadow_shadowmappcf)
5458                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5459                 }
5460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5461                         permutation |= SHADERPERMUTATION_REFLECTION;
5462                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5463                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5464                 if (rsurface.texture->reflectmasktexture)
5465                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5466                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5467                 {
5468                         // deluxemapping (light direction texture)
5469                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5471                         else
5472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5473                         permutation |= SHADERPERMUTATION_DIFFUSE;
5474                         if (specularscale > 0)
5475                         {
5476                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5477                                 if (r_shadow_glossexact.integer)
5478                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5479                         }
5480                 }
5481                 else if (r_glsl_deluxemapping.integer >= 2)
5482                 {
5483                         // fake deluxemapping (uniform light direction in tangentspace)
5484                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5485                         permutation |= SHADERPERMUTATION_DIFFUSE;
5486                         if (specularscale > 0)
5487                         {
5488                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5489                                 if (r_shadow_glossexact.integer)
5490                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5491                         }
5492                 }
5493                 else if (rsurface.uselightmaptexture)
5494                 {
5495                         // ordinary lightmapping (q1bsp, q3bsp)
5496                         mode = SHADERMODE_LIGHTMAP;
5497                 }
5498                 else
5499                 {
5500                         // ordinary vertex coloring (q3bsp)
5501                         mode = SHADERMODE_VERTEXCOLOR;
5502                 }
5503                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5504                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5505                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5506         }
5507         if(!allow_colormod)
5508                 colormod = dummy_colormod;
5509         switch(vid.renderpath)
5510         {
5511         case RENDERPATH_D3D9:
5512 #ifdef SUPPORTD3D
5513                 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);
5514                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5515                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5516                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5517                 if (mode == SHADERMODE_LIGHTSOURCE)
5518                 {
5519                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5520                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5521                 }
5522                 else
5523                 {
5524                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5525                         {
5526                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5527                         }
5528                 }
5529                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5530                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5531                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5532                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5533                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5534
5535                 if (mode == SHADERMODE_LIGHTSOURCE)
5536                 {
5537                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5538                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5539                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5540                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5541                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5542
5543                         // additive passes are only darkened by fog, not tinted
5544                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5545                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5546                 }
5547                 else
5548                 {
5549                         if (mode == SHADERMODE_FLATCOLOR)
5550                         {
5551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5552                         }
5553                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5554                         {
5555                                 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]);
5556                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5557                                 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);
5558                                 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);
5559                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5560                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5561                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5562                         }
5563                         else
5564                         {
5565                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5566                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5567                                 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);
5568                                 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);
5569                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5570                         }
5571                         // additive passes are only darkened by fog, not tinted
5572                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5573                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5574                         else
5575                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5576                         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);
5577                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5578                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5579                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5580                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5581                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5582                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5583                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5584                 }
5585                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5586                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5587                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5588                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5589                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5590                 if (rsurface.texture->pantstexture)
5591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5592                 else
5593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5594                 if (rsurface.texture->shirttexture)
5595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5596                 else
5597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5598                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5599                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5600                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5601                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5602                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5603                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5604                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5605
5606                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5607                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5608                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5609                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5610                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5611                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5612                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5614                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5615                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5616                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5617                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5618                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5619                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5620                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5621                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5622                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5623                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5624                 {
5625                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5626                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5627                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5628                 }
5629                 else
5630                 {
5631                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5632                 }
5633 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5634 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5635                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5636                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5637                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5638                 {
5639                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5640                         if (rsurface.rtlight)
5641                         {
5642                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5643                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5644                         }
5645                 }
5646 #endif
5647                 break;
5648         case RENDERPATH_D3D10:
5649                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5650                 break;
5651         case RENDERPATH_D3D11:
5652                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5653                 break;
5654         case RENDERPATH_GL20:
5655                 if (gl_mesh_separatearrays.integer)
5656                 {
5657                         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);
5658                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5659                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5660                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5661                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5662                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5663                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5664                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5665                 }
5666                 else
5667                 {
5668                         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);
5669                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5670                 }
5671                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5672                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5673                 if (mode == SHADERMODE_LIGHTSOURCE)
5674                 {
5675                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5676                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5677                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5678                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5679                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5680                         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);
5681         
5682                         // additive passes are only darkened by fog, not tinted
5683                         if (r_glsl_permutation->loc_FogColor >= 0)
5684                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5685                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5686                 }
5687                 else
5688                 {
5689                         if (mode == SHADERMODE_FLATCOLOR)
5690                         {
5691                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5692                         }
5693                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5694                         {
5695                                 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]);
5696                                 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]);
5697                                 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);
5698                                 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);
5699                                 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);
5700                                 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]);
5701                                 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]);
5702                         }
5703                         else
5704                         {
5705                                 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]);
5706                                 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]);
5707                                 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);
5708                                 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);
5709                                 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);
5710                         }
5711                         // additive passes are only darkened by fog, not tinted
5712                         if (r_glsl_permutation->loc_FogColor >= 0)
5713                         {
5714                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5715                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5716                                 else
5717                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5718                         }
5719                         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);
5720                         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]);
5721                         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]);
5722                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5723                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5724                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5725                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5726                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5727                 }
5728                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5729                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5730                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5731                 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]);
5732                 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]);
5733
5734                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5735                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5736                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5737                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5738                 {
5739                         if (rsurface.texture->pantstexture)
5740                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5741                         else
5742                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5743                 }
5744                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5745                 {
5746                         if (rsurface.texture->shirttexture)
5747                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5748                         else
5749                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5750                 }
5751                 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]);
5752                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5753                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5754                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5755                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5756                 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]);
5757                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5758
5759         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5760         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5761         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5762                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5763                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5764                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5765                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5766                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5767                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5768                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5769                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5770                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5771                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5772                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5773                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5774                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5775                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5776                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5777                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5778                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5779                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5780                 {
5781                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5782                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5783                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5784                 }
5785                 else
5786                 {
5787                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5788                 }
5789 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5790 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5791                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5792                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5793                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5794                 {
5795                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5796                         if (rsurface.rtlight)
5797                         {
5798                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5799                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5800                         }
5801                 }
5802                 CHECKGLERROR
5803                 break;
5804         case RENDERPATH_CGGL:
5805 #ifdef SUPPORTCG
5806                 if (gl_mesh_separatearrays.integer)
5807                 {
5808                         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);
5809                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5810                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5811                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5812                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5813                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5814                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5815                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5816                 }
5817                 else
5818                 {
5819                         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);
5820                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5821                 }
5822                 R_SetupShader_SetPermutationCG(mode, permutation);
5823                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5824                 if (mode == SHADERMODE_LIGHTSOURCE)
5825                 {
5826                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5827                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5828                 }
5829                 else
5830                 {
5831                         if (mode == SHADERMODE_LIGHTDIRECTION)
5832                         {
5833                                 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
5834                         }
5835                 }
5836                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5837                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5838                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5839                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5840                 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
5841                 CHECKGLERROR
5842
5843                 if (mode == SHADERMODE_LIGHTSOURCE)
5844                 {
5845                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5846                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5847                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5848                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5849                         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
5850
5851                         // additive passes are only darkened by fog, not tinted
5852                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5853                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5854                 }
5855                 else
5856                 {
5857                         if (mode == SHADERMODE_FLATCOLOR)
5858                         {
5859                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5860                         }
5861                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5862                         {
5863                                 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
5864                                 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
5865                                 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
5866                                 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
5867                                 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
5868                                 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
5869                                 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
5870                         }
5871                         else
5872                         {
5873                                 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
5874                                 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
5875                                 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
5876                                 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
5877                                 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
5878                         }
5879                         // additive passes are only darkened by fog, not tinted
5880                         if (r_cg_permutation->fp_FogColor)
5881                         {
5882                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5883                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5884                                 else
5885                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5886                                 CHECKCGERROR
5887                         }
5888                         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
5889                         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
5890                         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
5891                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5892                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5893                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5894                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5895                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5896                 }
5897                 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
5898                 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
5899                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5900                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5901                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5902                 if (r_cg_permutation->fp_Color_Pants)
5903                 {
5904                         if (rsurface.texture->pantstexture)
5905                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5906                         else
5907                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5908                         CHECKCGERROR
5909                 }
5910                 if (r_cg_permutation->fp_Color_Shirt)
5911                 {
5912                         if (rsurface.texture->shirttexture)
5913                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5914                         else
5915                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5916                         CHECKCGERROR
5917                 }
5918                 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
5919                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5920                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5921                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5922                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5923                 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
5924                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5925
5926         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5927         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5928         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5929                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5930                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5931                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5932                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5933                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5934                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5935                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5936                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5937                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5938                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5939                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5940                 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
5941                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5942                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5943                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5944                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5945                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5946                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5947                 {
5948                         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
5949                         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
5950                         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
5951                 }
5952                 else
5953                 {
5954                         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
5955                 }
5956                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5957                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5958                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5959                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5960                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5961                 {
5962                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5963                         if (rsurface.rtlight)
5964                         {
5965                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5966                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5967                         }
5968                 }
5969
5970                 CHECKGLERROR
5971 #endif
5972                 break;
5973         case RENDERPATH_GL13:
5974         case RENDERPATH_GL11:
5975                 break;
5976         }
5977 }
5978
5979 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5980 {
5981         // select a permutation of the lighting shader appropriate to this
5982         // combination of texture, entity, light source, and fogging, only use the
5983         // minimum features necessary to avoid wasting rendering time in the
5984         // fragment shader on features that are not being used
5985         unsigned int permutation = 0;
5986         unsigned int mode = 0;
5987         const float *lightcolorbase = rtlight->currentcolor;
5988         float ambientscale = rtlight->ambientscale;
5989         float diffusescale = rtlight->diffusescale;
5990         float specularscale = rtlight->specularscale;
5991         // this is the location of the light in view space
5992         vec3_t viewlightorigin;
5993         // this transforms from view space (camera) to light space (cubemap)
5994         matrix4x4_t viewtolight;
5995         matrix4x4_t lighttoview;
5996         float viewtolight16f[16];
5997         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5998         // light source
5999         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6000         if (rtlight->currentcubemap != r_texture_whitecube)
6001                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6002         if (diffusescale > 0)
6003                 permutation |= SHADERPERMUTATION_DIFFUSE;
6004         if (specularscale > 0)
6005         {
6006                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6007                 if (r_shadow_glossexact.integer)
6008                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6009         }
6010         if (r_shadow_usingshadowmap2d)
6011         {
6012                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6013                 if (r_shadow_shadowmapvsdct)
6014                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6015
6016                 if (r_shadow_shadowmapsampler)
6017                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6018                 if (r_shadow_shadowmappcf > 1)
6019                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6020                 else if (r_shadow_shadowmappcf)
6021                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6022         }
6023         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6024         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6025         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6026         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6027         switch(vid.renderpath)
6028         {
6029         case RENDERPATH_D3D9:
6030 #ifdef SUPPORTD3D
6031                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6032                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6033                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6037                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6039                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6040                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6041                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6042
6043                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6044                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6049 #endif
6050                 break;
6051         case RENDERPATH_D3D10:
6052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6053                 break;
6054         case RENDERPATH_D3D11:
6055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6056                 break;
6057         case RENDERPATH_GL20:
6058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6059                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6060                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6061                 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);
6062                 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);
6063                 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);
6064                 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]);
6065                 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]);
6066                 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));
6067                 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]);
6068                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6069
6070                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6071                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6072                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6073                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6074                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6075                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6076                 break;
6077         case RENDERPATH_CGGL:
6078 #ifdef SUPPORTCG
6079                 R_SetupShader_SetPermutationCG(mode, permutation);
6080                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6081                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6082                 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
6083                 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
6084                 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
6085                 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
6086                 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
6087                 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
6088                 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
6089                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6090
6091                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6092                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6093                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6094                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6095                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6096                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6097 #endif
6098                 break;
6099         case RENDERPATH_GL13:
6100         case RENDERPATH_GL11:
6101                 break;
6102         }
6103 }
6104
6105 #define SKINFRAME_HASH 1024
6106
6107 typedef struct
6108 {
6109         int loadsequence; // incremented each level change
6110         memexpandablearray_t array;
6111         skinframe_t *hash[SKINFRAME_HASH];
6112 }
6113 r_skinframe_t;
6114 r_skinframe_t r_skinframe;
6115
6116 void R_SkinFrame_PrepareForPurge(void)
6117 {
6118         r_skinframe.loadsequence++;
6119         // wrap it without hitting zero
6120         if (r_skinframe.loadsequence >= 200)
6121                 r_skinframe.loadsequence = 1;
6122 }
6123
6124 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6125 {
6126         if (!skinframe)
6127                 return;
6128         // mark the skinframe as used for the purging code
6129         skinframe->loadsequence = r_skinframe.loadsequence;
6130 }
6131
6132 void R_SkinFrame_Purge(void)
6133 {
6134         int i;
6135         skinframe_t *s;
6136         for (i = 0;i < SKINFRAME_HASH;i++)
6137         {
6138                 for (s = r_skinframe.hash[i];s;s = s->next)
6139                 {
6140                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6141                         {
6142                                 if (s->merged == s->base)
6143                                         s->merged = NULL;
6144                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6145                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6146                                 R_PurgeTexture(s->merged);s->merged = NULL;
6147                                 R_PurgeTexture(s->base  );s->base   = NULL;
6148                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6149                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6150                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6151                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6152                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6153                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6154                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6155                                 s->loadsequence = 0;
6156                         }
6157                 }
6158         }
6159 }
6160
6161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6162         skinframe_t *item;
6163         char basename[MAX_QPATH];
6164
6165         Image_StripImageExtension(name, basename, sizeof(basename));
6166
6167         if( last == NULL ) {
6168                 int hashindex;
6169                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6170                 item = r_skinframe.hash[hashindex];
6171         } else {
6172                 item = last->next;
6173         }
6174
6175         // linearly search through the hash bucket
6176         for( ; item ; item = item->next ) {
6177                 if( !strcmp( item->basename, basename ) ) {
6178                         return item;
6179                 }
6180         }
6181         return NULL;
6182 }
6183
6184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6185 {
6186         skinframe_t *item;
6187         int hashindex;
6188         char basename[MAX_QPATH];
6189
6190         Image_StripImageExtension(name, basename, sizeof(basename));
6191
6192         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6193         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6194                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6195                         break;
6196
6197         if (!item) {
6198                 rtexture_t *dyntexture;
6199                 // check whether its a dynamic texture
6200                 dyntexture = CL_GetDynTexture( basename );
6201                 if (!add && !dyntexture)
6202                         return NULL;
6203                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6204                 memset(item, 0, sizeof(*item));
6205                 strlcpy(item->basename, basename, sizeof(item->basename));
6206                 item->base = dyntexture; // either NULL or dyntexture handle
6207                 item->textureflags = textureflags;
6208                 item->comparewidth = comparewidth;
6209                 item->compareheight = compareheight;
6210                 item->comparecrc = comparecrc;
6211                 item->next = r_skinframe.hash[hashindex];
6212                 r_skinframe.hash[hashindex] = item;
6213         }
6214         else if( item->base == NULL )
6215         {
6216                 rtexture_t *dyntexture;
6217                 // check whether its a dynamic texture
6218                 // 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]
6219                 dyntexture = CL_GetDynTexture( basename );
6220                 item->base = dyntexture; // either NULL or dyntexture handle
6221         }
6222
6223         R_SkinFrame_MarkUsed(item);
6224         return item;
6225 }
6226
6227 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6228         { \
6229                 unsigned long long avgcolor[5], wsum; \
6230                 int pix, comp, w; \
6231                 avgcolor[0] = 0; \
6232                 avgcolor[1] = 0; \
6233                 avgcolor[2] = 0; \
6234                 avgcolor[3] = 0; \
6235                 avgcolor[4] = 0; \
6236                 wsum = 0; \
6237                 for(pix = 0; pix < cnt; ++pix) \
6238                 { \
6239                         w = 0; \
6240                         for(comp = 0; comp < 3; ++comp) \
6241                                 w += getpixel; \
6242                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6243                         { \
6244                                 ++wsum; \
6245                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6246                                 w = getpixel; \
6247                                 for(comp = 0; comp < 3; ++comp) \
6248                                         avgcolor[comp] += getpixel * w; \
6249                                 avgcolor[3] += w; \
6250                         } \
6251                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6252                         avgcolor[4] += getpixel; \
6253                 } \
6254                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6255                         avgcolor[3] = 1; \
6256                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6257                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6258                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6259                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6260         }
6261
6262 extern cvar_t gl_picmip;
6263 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6264 {
6265         int j;
6266         unsigned char *pixels;
6267         unsigned char *bumppixels;
6268         unsigned char *basepixels = NULL;
6269         int basepixels_width = 0;
6270         int basepixels_height = 0;
6271         skinframe_t *skinframe;
6272         rtexture_t *ddsbase = NULL;
6273         qboolean ddshasalpha = false;
6274         float ddsavgcolor[4];
6275         char basename[MAX_QPATH];
6276         int miplevel = R_PicmipForFlags(textureflags);
6277         int savemiplevel = miplevel;
6278         int mymiplevel;
6279
6280         if (cls.state == ca_dedicated)
6281                 return NULL;
6282
6283         // return an existing skinframe if already loaded
6284         // if loading of the first image fails, don't make a new skinframe as it
6285         // would cause all future lookups of this to be missing
6286         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6287         if (skinframe && skinframe->base)
6288                 return skinframe;
6289
6290         Image_StripImageExtension(name, basename, sizeof(basename));
6291
6292         // check for DDS texture file first
6293         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6294         {
6295                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6296                 if (basepixels == NULL)
6297                         return NULL;
6298         }
6299
6300         // FIXME handle miplevel
6301
6302         if (developer_loading.integer)
6303                 Con_Printf("loading skin \"%s\"\n", name);
6304
6305         // we've got some pixels to store, so really allocate this new texture now
6306         if (!skinframe)
6307                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6308         skinframe->stain = NULL;
6309         skinframe->merged = NULL;
6310         skinframe->base = NULL;
6311         skinframe->pants = NULL;
6312         skinframe->shirt = NULL;
6313         skinframe->nmap = NULL;
6314         skinframe->gloss = NULL;
6315         skinframe->glow = NULL;
6316         skinframe->fog = NULL;
6317         skinframe->reflect = NULL;
6318         skinframe->hasalpha = false;
6319
6320         if (ddsbase)
6321         {
6322                 skinframe->base = ddsbase;
6323                 skinframe->hasalpha = ddshasalpha;
6324                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6325                 if (r_loadfog && skinframe->hasalpha)
6326                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6327                 //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]);
6328         }
6329         else
6330         {
6331                 basepixels_width = image_width;
6332                 basepixels_height = image_height;
6333                 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);
6334                 if (textureflags & TEXF_ALPHA)
6335                 {
6336                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6337                         {
6338                                 if (basepixels[j] < 255)
6339                                 {
6340                                         skinframe->hasalpha = true;
6341                                         break;
6342                                 }
6343                         }
6344                         if (r_loadfog && skinframe->hasalpha)
6345                         {
6346                                 // has transparent pixels
6347                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6348                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6349                                 {
6350                                         pixels[j+0] = 255;
6351                                         pixels[j+1] = 255;
6352                                         pixels[j+2] = 255;
6353                                         pixels[j+3] = basepixels[j+3];
6354                                 }
6355                                 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);
6356                                 Mem_Free(pixels);
6357                         }
6358                 }
6359                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6360                 //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]);
6361                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6362                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6363                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6364                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6365         }
6366
6367         if (r_loaddds)
6368         {
6369                 mymiplevel = savemiplevel;
6370                 if (r_loadnormalmap)
6371                         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);
6372                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6373                 if (r_loadgloss)
6374                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6375                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6376                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6377                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6378         }
6379
6380         // _norm is the name used by tenebrae and has been adopted as standard
6381         if (r_loadnormalmap && skinframe->nmap == NULL)
6382         {
6383                 mymiplevel = savemiplevel;
6384                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6385                 {
6386                         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);
6387                         Mem_Free(pixels);
6388                         pixels = NULL;
6389                 }
6390                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6391                 {
6392                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6393                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6394                         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);
6395                         Mem_Free(pixels);
6396                         Mem_Free(bumppixels);
6397                 }
6398                 else if (r_shadow_bumpscale_basetexture.value > 0)
6399                 {
6400                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6401                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6402                         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);
6403                         Mem_Free(pixels);
6404                 }
6405                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6406                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6407         }
6408
6409         // _luma is supported only for tenebrae compatibility
6410         // _glow is the preferred name
6411         mymiplevel = savemiplevel;
6412         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))))
6413         {
6414                 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);
6415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6416                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6417                 Mem_Free(pixels);pixels = NULL;
6418         }
6419
6420         mymiplevel = savemiplevel;
6421         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6422         {
6423                 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);
6424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6425                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6426                 Mem_Free(pixels);
6427                 pixels = NULL;
6428         }
6429
6430         mymiplevel = savemiplevel;
6431         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6432         {
6433                 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);
6434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6435                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6436                 Mem_Free(pixels);
6437                 pixels = NULL;
6438         }
6439
6440         mymiplevel = savemiplevel;
6441         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6442         {
6443                 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);
6444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6445                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6446                 Mem_Free(pixels);
6447                 pixels = NULL;
6448         }
6449
6450         mymiplevel = savemiplevel;
6451         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6452         {
6453                 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);
6454                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6455                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6456                 Mem_Free(pixels);
6457                 pixels = NULL;
6458         }
6459
6460         if (basepixels)
6461                 Mem_Free(basepixels);
6462
6463         return skinframe;
6464 }
6465
6466 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6467 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6468 {
6469         int i;
6470         unsigned char *temp1, *temp2;
6471         skinframe_t *skinframe;
6472
6473         if (cls.state == ca_dedicated)
6474                 return NULL;
6475
6476         // if already loaded just return it, otherwise make a new skinframe
6477         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6478         if (skinframe && skinframe->base)
6479                 return skinframe;
6480
6481         skinframe->stain = NULL;
6482         skinframe->merged = NULL;
6483         skinframe->base = NULL;
6484         skinframe->pants = NULL;
6485         skinframe->shirt = NULL;
6486         skinframe->nmap = NULL;
6487         skinframe->gloss = NULL;
6488         skinframe->glow = NULL;
6489         skinframe->fog = NULL;
6490         skinframe->reflect = NULL;
6491         skinframe->hasalpha = false;
6492
6493         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6494         if (!skindata)
6495                 return NULL;
6496
6497         if (developer_loading.integer)
6498                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6499
6500         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6501         {
6502                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6503                 temp2 = temp1 + width * height * 4;
6504                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6505                 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);
6506                 Mem_Free(temp1);
6507         }
6508         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6509         if (textureflags & TEXF_ALPHA)
6510         {
6511                 for (i = 3;i < width * height * 4;i += 4)
6512                 {
6513                         if (skindata[i] < 255)
6514                         {
6515                                 skinframe->hasalpha = true;
6516                                 break;
6517                         }
6518                 }
6519                 if (r_loadfog && skinframe->hasalpha)
6520                 {
6521                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6522                         memcpy(fogpixels, skindata, width * height * 4);
6523                         for (i = 0;i < width * height * 4;i += 4)
6524                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6525                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6526                         Mem_Free(fogpixels);
6527                 }
6528         }
6529
6530         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6531         //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]);
6532
6533         return skinframe;
6534 }
6535
6536 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6537 {
6538         int i;
6539         int featuresmask;
6540         skinframe_t *skinframe;
6541
6542         if (cls.state == ca_dedicated)
6543                 return NULL;
6544
6545         // if already loaded just return it, otherwise make a new skinframe
6546         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6547         if (skinframe && skinframe->base)
6548                 return skinframe;
6549
6550         skinframe->stain = NULL;
6551         skinframe->merged = NULL;
6552         skinframe->base = NULL;
6553         skinframe->pants = NULL;
6554         skinframe->shirt = NULL;
6555         skinframe->nmap = NULL;
6556         skinframe->gloss = NULL;
6557         skinframe->glow = NULL;
6558         skinframe->fog = NULL;
6559         skinframe->reflect = NULL;
6560         skinframe->hasalpha = false;
6561
6562         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6563         if (!skindata)
6564                 return NULL;
6565
6566         if (developer_loading.integer)
6567                 Con_Printf("loading quake skin \"%s\"\n", name);
6568
6569         // 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)
6570         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6571         memcpy(skinframe->qpixels, skindata, width*height);
6572         skinframe->qwidth = width;
6573         skinframe->qheight = height;
6574
6575         featuresmask = 0;
6576         for (i = 0;i < width * height;i++)
6577                 featuresmask |= palette_featureflags[skindata[i]];
6578
6579         skinframe->hasalpha = false;
6580         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6581         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6582         skinframe->qgeneratemerged = true;
6583         skinframe->qgeneratebase = skinframe->qhascolormapping;
6584         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6585
6586         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6587         //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]);
6588
6589         return skinframe;
6590 }
6591
6592 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6593 {
6594         int width;
6595         int height;
6596         unsigned char *skindata;
6597
6598         if (!skinframe->qpixels)
6599                 return;
6600
6601         if (!skinframe->qhascolormapping)
6602                 colormapped = false;
6603
6604         if (colormapped)
6605         {
6606                 if (!skinframe->qgeneratebase)
6607                         return;
6608         }
6609         else
6610         {
6611                 if (!skinframe->qgeneratemerged)
6612                         return;
6613         }
6614
6615         width = skinframe->qwidth;
6616         height = skinframe->qheight;
6617         skindata = skinframe->qpixels;
6618
6619         if (skinframe->qgeneratenmap)
6620         {
6621                 unsigned char *temp1, *temp2;
6622                 skinframe->qgeneratenmap = false;
6623                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6624                 temp2 = temp1 + width * height * 4;
6625                 // use either a custom palette or the quake palette
6626                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6627                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6628                 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);
6629                 Mem_Free(temp1);
6630         }
6631
6632         if (skinframe->qgenerateglow)
6633         {
6634                 skinframe->qgenerateglow = false;
6635                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6636         }
6637
6638         if (colormapped)
6639         {
6640                 skinframe->qgeneratebase = false;
6641                 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);
6642                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6643                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6644         }
6645         else
6646         {
6647                 skinframe->qgeneratemerged = false;
6648                 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);
6649         }
6650
6651         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6652         {
6653                 Mem_Free(skinframe->qpixels);
6654                 skinframe->qpixels = NULL;
6655         }
6656 }
6657
6658 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)
6659 {
6660         int i;
6661         skinframe_t *skinframe;
6662
6663         if (cls.state == ca_dedicated)
6664                 return NULL;
6665
6666         // if already loaded just return it, otherwise make a new skinframe
6667         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6668         if (skinframe && skinframe->base)
6669                 return skinframe;
6670
6671         skinframe->stain = NULL;
6672         skinframe->merged = NULL;
6673         skinframe->base = NULL;
6674         skinframe->pants = NULL;
6675         skinframe->shirt = NULL;
6676         skinframe->nmap = NULL;
6677         skinframe->gloss = NULL;
6678         skinframe->glow = NULL;
6679         skinframe->fog = NULL;
6680         skinframe->reflect = NULL;
6681         skinframe->hasalpha = false;
6682
6683         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6684         if (!skindata)
6685                 return NULL;
6686
6687         if (developer_loading.integer)
6688                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6689
6690         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6691         if (textureflags & TEXF_ALPHA)
6692         {
6693                 for (i = 0;i < width * height;i++)
6694                 {
6695                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6696                         {
6697                                 skinframe->hasalpha = true;
6698                                 break;
6699                         }
6700                 }
6701                 if (r_loadfog && skinframe->hasalpha)
6702                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6703         }
6704
6705         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6706         //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]);
6707
6708         return skinframe;
6709 }
6710
6711 skinframe_t *R_SkinFrame_LoadMissing(void)
6712 {
6713         skinframe_t *skinframe;
6714
6715         if (cls.state == ca_dedicated)
6716                 return NULL;
6717
6718         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6719         skinframe->stain = NULL;
6720         skinframe->merged = NULL;
6721         skinframe->base = NULL;
6722         skinframe->pants = NULL;
6723         skinframe->shirt = NULL;
6724         skinframe->nmap = NULL;
6725         skinframe->gloss = NULL;
6726         skinframe->glow = NULL;
6727         skinframe->fog = NULL;
6728         skinframe->reflect = NULL;
6729         skinframe->hasalpha = false;
6730
6731         skinframe->avgcolor[0] = rand() / RAND_MAX;
6732         skinframe->avgcolor[1] = rand() / RAND_MAX;
6733         skinframe->avgcolor[2] = rand() / RAND_MAX;
6734         skinframe->avgcolor[3] = 1;
6735
6736         return skinframe;
6737 }
6738
6739 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6740 typedef struct suffixinfo_s
6741 {
6742         const char *suffix;
6743         qboolean flipx, flipy, flipdiagonal;
6744 }
6745 suffixinfo_t;
6746 static suffixinfo_t suffix[3][6] =
6747 {
6748         {
6749                 {"px",   false, false, false},
6750                 {"nx",   false, false, false},
6751                 {"py",   false, false, false},
6752                 {"ny",   false, false, false},
6753                 {"pz",   false, false, false},
6754                 {"nz",   false, false, false}
6755         },
6756         {
6757                 {"posx", false, false, false},
6758                 {"negx", false, false, false},
6759                 {"posy", false, false, false},
6760                 {"negy", false, false, false},
6761                 {"posz", false, false, false},
6762                 {"negz", false, false, false}
6763         },
6764         {
6765                 {"rt",    true, false,  true},
6766                 {"lf",   false,  true,  true},
6767                 {"ft",    true,  true, false},
6768                 {"bk",   false, false, false},
6769                 {"up",    true, false,  true},
6770                 {"dn",    true, false,  true}
6771         }
6772 };
6773
6774 static int componentorder[4] = {0, 1, 2, 3};
6775
6776 rtexture_t *R_LoadCubemap(const char *basename)
6777 {
6778         int i, j, cubemapsize;
6779         unsigned char *cubemappixels, *image_buffer;
6780         rtexture_t *cubemaptexture;
6781         char name[256];
6782         // must start 0 so the first loadimagepixels has no requested width/height
6783         cubemapsize = 0;
6784         cubemappixels = NULL;
6785         cubemaptexture = NULL;
6786         // keep trying different suffix groups (posx, px, rt) until one loads
6787         for (j = 0;j < 3 && !cubemappixels;j++)
6788         {
6789                 // load the 6 images in the suffix group
6790                 for (i = 0;i < 6;i++)
6791                 {
6792                         // generate an image name based on the base and and suffix
6793                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6794                         // load it
6795                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6796                         {
6797                                 // an image loaded, make sure width and height are equal
6798                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6799                                 {
6800                                         // if this is the first image to load successfully, allocate the cubemap memory
6801                                         if (!cubemappixels && image_width >= 1)
6802                                         {
6803                                                 cubemapsize = image_width;
6804                                                 // note this clears to black, so unavailable sides are black
6805                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6806                                         }
6807                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6808                                         if (cubemappixels)
6809                                                 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);
6810                                 }
6811                                 else
6812                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6813                                 // free the image
6814                                 Mem_Free(image_buffer);
6815                         }
6816                 }
6817         }
6818         // if a cubemap loaded, upload it
6819         if (cubemappixels)
6820         {
6821                 if (developer_loading.integer)
6822                         Con_Printf("loading cubemap \"%s\"\n", basename);
6823
6824                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6825                 Mem_Free(cubemappixels);
6826         }
6827         else
6828         {
6829                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6830                 if (developer_loading.integer)
6831                 {
6832                         Con_Printf("(tried tried images ");
6833                         for (j = 0;j < 3;j++)
6834                                 for (i = 0;i < 6;i++)
6835                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6836                         Con_Print(" and was unable to find any of them).\n");
6837                 }
6838         }
6839         return cubemaptexture;
6840 }
6841
6842 rtexture_t *R_GetCubemap(const char *basename)
6843 {
6844         int i;
6845         for (i = 0;i < r_texture_numcubemaps;i++)
6846                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6847                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6848         if (i >= MAX_CUBEMAPS)
6849                 return r_texture_whitecube;
6850         r_texture_numcubemaps++;
6851         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6852         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6853         return r_texture_cubemaps[i].texture;
6854 }
6855
6856 void R_FreeCubemaps(void)
6857 {
6858         int i;
6859         for (i = 0;i < r_texture_numcubemaps;i++)
6860         {
6861                 if (developer_loading.integer)
6862                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6863                 if (r_texture_cubemaps[i].texture)
6864                         R_FreeTexture(r_texture_cubemaps[i].texture);
6865         }
6866         r_texture_numcubemaps = 0;
6867 }
6868
6869 void R_Main_FreeViewCache(void)
6870 {
6871         if (r_refdef.viewcache.entityvisible)
6872                 Mem_Free(r_refdef.viewcache.entityvisible);
6873         if (r_refdef.viewcache.world_pvsbits)
6874                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6875         if (r_refdef.viewcache.world_leafvisible)
6876                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6877         if (r_refdef.viewcache.world_surfacevisible)
6878                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6879         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6880 }
6881
6882 void R_Main_ResizeViewCache(void)
6883 {
6884         int numentities = r_refdef.scene.numentities;
6885         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6886         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6887         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6888         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6889         if (r_refdef.viewcache.maxentities < numentities)
6890         {
6891                 r_refdef.viewcache.maxentities = numentities;
6892                 if (r_refdef.viewcache.entityvisible)
6893                         Mem_Free(r_refdef.viewcache.entityvisible);
6894                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6895         }
6896         if (r_refdef.viewcache.world_numclusters != numclusters)
6897         {
6898                 r_refdef.viewcache.world_numclusters = numclusters;
6899                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6900                 if (r_refdef.viewcache.world_pvsbits)
6901                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6902                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6903         }
6904         if (r_refdef.viewcache.world_numleafs != numleafs)
6905         {
6906                 r_refdef.viewcache.world_numleafs = numleafs;
6907                 if (r_refdef.viewcache.world_leafvisible)
6908                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6909                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6910         }
6911         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6912         {
6913                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6914                 if (r_refdef.viewcache.world_surfacevisible)
6915                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6916                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6917         }
6918 }
6919
6920 extern rtexture_t *loadingscreentexture;
6921 void gl_main_start(void)
6922 {
6923         loadingscreentexture = NULL;
6924         r_texture_blanknormalmap = NULL;
6925         r_texture_white = NULL;
6926         r_texture_grey128 = NULL;
6927         r_texture_black = NULL;
6928         r_texture_whitecube = NULL;
6929         r_texture_normalizationcube = NULL;
6930         r_texture_fogattenuation = NULL;
6931         r_texture_fogheighttexture = NULL;
6932         r_texture_gammaramps = NULL;
6933         r_texture_numcubemaps = 0;
6934
6935         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6936         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6937
6938         switch(vid.renderpath)
6939         {
6940         case RENDERPATH_GL20:
6941         case RENDERPATH_CGGL:
6942         case RENDERPATH_D3D9:
6943         case RENDERPATH_D3D10:
6944         case RENDERPATH_D3D11:
6945                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6946                 Cvar_SetValueQuick(&gl_combine, 1);
6947                 Cvar_SetValueQuick(&r_glsl, 1);
6948                 r_loadnormalmap = true;
6949                 r_loadgloss = true;
6950                 r_loadfog = false;
6951                 break;
6952         case RENDERPATH_GL13:
6953                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6954                 Cvar_SetValueQuick(&gl_combine, 1);
6955                 Cvar_SetValueQuick(&r_glsl, 0);
6956                 r_loadnormalmap = false;
6957                 r_loadgloss = false;
6958                 r_loadfog = true;
6959                 break;
6960         case RENDERPATH_GL11:
6961                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6962                 Cvar_SetValueQuick(&gl_combine, 0);
6963                 Cvar_SetValueQuick(&r_glsl, 0);
6964                 r_loadnormalmap = false;
6965                 r_loadgloss = false;
6966                 r_loadfog = true;
6967                 break;
6968         }
6969
6970         R_AnimCache_Free();
6971         R_FrameData_Reset();
6972
6973         r_numqueries = 0;
6974         r_maxqueries = 0;
6975         memset(r_queries, 0, sizeof(r_queries));
6976
6977         r_qwskincache = NULL;
6978         r_qwskincache_size = 0;
6979
6980         // set up r_skinframe loading system for textures
6981         memset(&r_skinframe, 0, sizeof(r_skinframe));
6982         r_skinframe.loadsequence = 1;
6983         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6984
6985         r_main_texturepool = R_AllocTexturePool();
6986         R_BuildBlankTextures();
6987         R_BuildNoTexture();
6988         if (vid.support.arb_texture_cube_map)
6989         {
6990                 R_BuildWhiteCube();
6991                 R_BuildNormalizationCube();
6992         }
6993         r_texture_fogattenuation = NULL;
6994         r_texture_fogheighttexture = NULL;
6995         r_texture_gammaramps = NULL;
6996         //r_texture_fogintensity = NULL;
6997         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6998         memset(&r_waterstate, 0, sizeof(r_waterstate));
6999         r_glsl_permutation = NULL;
7000         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7001         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7002         glslshaderstring = NULL;
7003 #ifdef SUPPORTCG
7004         r_cg_permutation = NULL;
7005         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7006         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7007         cgshaderstring = NULL;
7008 #endif
7009 #ifdef SUPPORTD3D
7010         r_hlsl_permutation = NULL;
7011         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7012         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7013         hlslshaderstring = NULL;
7014 #endif
7015         memset(&r_svbsp, 0, sizeof (r_svbsp));
7016
7017         r_refdef.fogmasktable_density = 0;
7018 }
7019
7020 void gl_main_shutdown(void)
7021 {
7022         R_AnimCache_Free();
7023         R_FrameData_Reset();
7024
7025         R_Main_FreeViewCache();
7026
7027         switch(vid.renderpath)
7028         {
7029         case RENDERPATH_GL11:
7030         case RENDERPATH_GL13:
7031         case RENDERPATH_GL20:
7032         case RENDERPATH_CGGL:
7033                 if (r_maxqueries)
7034                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7035                 break;
7036         case RENDERPATH_D3D9:
7037                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7038                 break;
7039         case RENDERPATH_D3D10:
7040                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7041                 break;
7042         case RENDERPATH_D3D11:
7043                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7044                 break;
7045         }
7046
7047         r_numqueries = 0;
7048         r_maxqueries = 0;
7049         memset(r_queries, 0, sizeof(r_queries));
7050
7051         r_qwskincache = NULL;
7052         r_qwskincache_size = 0;
7053
7054         // clear out the r_skinframe state
7055         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7056         memset(&r_skinframe, 0, sizeof(r_skinframe));
7057
7058         if (r_svbsp.nodes)
7059                 Mem_Free(r_svbsp.nodes);
7060         memset(&r_svbsp, 0, sizeof (r_svbsp));
7061         R_FreeTexturePool(&r_main_texturepool);
7062         loadingscreentexture = NULL;
7063         r_texture_blanknormalmap = NULL;
7064         r_texture_white = NULL;
7065         r_texture_grey128 = NULL;
7066         r_texture_black = NULL;
7067         r_texture_whitecube = NULL;
7068         r_texture_normalizationcube = NULL;
7069         r_texture_fogattenuation = NULL;
7070         r_texture_fogheighttexture = NULL;
7071         r_texture_gammaramps = NULL;
7072         r_texture_numcubemaps = 0;
7073         //r_texture_fogintensity = NULL;
7074         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7075         memset(&r_waterstate, 0, sizeof(r_waterstate));
7076         R_GLSL_Restart_f();
7077 }
7078
7079 extern void CL_ParseEntityLump(char *entitystring);
7080 void gl_main_newmap(void)
7081 {
7082         // FIXME: move this code to client
7083         char *entities, entname[MAX_QPATH];
7084         if (r_qwskincache)
7085                 Mem_Free(r_qwskincache);
7086         r_qwskincache = NULL;
7087         r_qwskincache_size = 0;
7088         if (cl.worldmodel)
7089         {
7090                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7091                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7092                 {
7093                         CL_ParseEntityLump(entities);
7094                         Mem_Free(entities);
7095                         return;
7096                 }
7097                 if (cl.worldmodel->brush.entities)
7098                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7099         }
7100         R_Main_FreeViewCache();
7101
7102         R_FrameData_Reset();
7103 }
7104
7105 void GL_Main_Init(void)
7106 {
7107         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7108
7109         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7110         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7111         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7112         if (gamemode == GAME_NEHAHRA)
7113         {
7114                 Cvar_RegisterVariable (&gl_fogenable);
7115                 Cvar_RegisterVariable (&gl_fogdensity);
7116                 Cvar_RegisterVariable (&gl_fogred);
7117                 Cvar_RegisterVariable (&gl_foggreen);
7118                 Cvar_RegisterVariable (&gl_fogblue);
7119                 Cvar_RegisterVariable (&gl_fogstart);
7120                 Cvar_RegisterVariable (&gl_fogend);
7121                 Cvar_RegisterVariable (&gl_skyclip);
7122         }
7123         Cvar_RegisterVariable(&r_motionblur);
7124         Cvar_RegisterVariable(&r_motionblur_maxblur);
7125         Cvar_RegisterVariable(&r_motionblur_bmin);
7126         Cvar_RegisterVariable(&r_motionblur_vmin);
7127         Cvar_RegisterVariable(&r_motionblur_vmax);
7128         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7129         Cvar_RegisterVariable(&r_motionblur_randomize);
7130         Cvar_RegisterVariable(&r_damageblur);
7131         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7132         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7133         Cvar_RegisterVariable(&r_equalize_entities_by);
7134         Cvar_RegisterVariable(&r_equalize_entities_to);
7135         Cvar_RegisterVariable(&r_depthfirst);
7136         Cvar_RegisterVariable(&r_useinfinitefarclip);
7137         Cvar_RegisterVariable(&r_farclip_base);
7138         Cvar_RegisterVariable(&r_farclip_world);
7139         Cvar_RegisterVariable(&r_nearclip);
7140         Cvar_RegisterVariable(&r_showbboxes);
7141         Cvar_RegisterVariable(&r_showsurfaces);
7142         Cvar_RegisterVariable(&r_showtris);
7143         Cvar_RegisterVariable(&r_shownormals);
7144         Cvar_RegisterVariable(&r_showlighting);
7145         Cvar_RegisterVariable(&r_showshadowvolumes);
7146         Cvar_RegisterVariable(&r_showcollisionbrushes);
7147         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7148         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7149         Cvar_RegisterVariable(&r_showdisabledepthtest);
7150         Cvar_RegisterVariable(&r_drawportals);
7151         Cvar_RegisterVariable(&r_drawentities);
7152         Cvar_RegisterVariable(&r_draw2d);
7153         Cvar_RegisterVariable(&r_drawworld);
7154         Cvar_RegisterVariable(&r_cullentities_trace);
7155         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7156         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7157         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7158         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7159         Cvar_RegisterVariable(&r_drawviewmodel);
7160         Cvar_RegisterVariable(&r_drawexteriormodel);
7161         Cvar_RegisterVariable(&r_speeds);
7162         Cvar_RegisterVariable(&r_fullbrights);
7163         Cvar_RegisterVariable(&r_wateralpha);
7164         Cvar_RegisterVariable(&r_dynamic);
7165         Cvar_RegisterVariable(&r_fullbright);
7166         Cvar_RegisterVariable(&r_shadows);
7167         Cvar_RegisterVariable(&r_shadows_darken);
7168         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7169         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7170         Cvar_RegisterVariable(&r_shadows_throwdistance);
7171         Cvar_RegisterVariable(&r_shadows_throwdirection);
7172         Cvar_RegisterVariable(&r_shadows_focus);
7173         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7174         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7175         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7176         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7177         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7178         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7179         Cvar_RegisterVariable(&r_fog_exp2);
7180         Cvar_RegisterVariable(&r_drawfog);
7181         Cvar_RegisterVariable(&r_transparentdepthmasking);
7182         Cvar_RegisterVariable(&r_texture_dds_load);
7183         Cvar_RegisterVariable(&r_texture_dds_save);
7184         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7185         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7186         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7187         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7188         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7189         Cvar_RegisterVariable(&r_textureunits);
7190         Cvar_RegisterVariable(&gl_combine);
7191         Cvar_RegisterVariable(&r_glsl);
7192         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7193         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7194         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7195         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7196         Cvar_RegisterVariable(&r_glsl_postprocess);
7197         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7198         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7199         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7200         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7201         Cvar_RegisterVariable(&r_water);
7202         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7203         Cvar_RegisterVariable(&r_water_clippingplanebias);
7204         Cvar_RegisterVariable(&r_water_refractdistort);
7205         Cvar_RegisterVariable(&r_water_reflectdistort);
7206         Cvar_RegisterVariable(&r_lerpsprites);
7207         Cvar_RegisterVariable(&r_lerpmodels);
7208         Cvar_RegisterVariable(&r_lerplightstyles);
7209         Cvar_RegisterVariable(&r_waterscroll);
7210         Cvar_RegisterVariable(&r_bloom);
7211         Cvar_RegisterVariable(&r_bloom_colorscale);
7212         Cvar_RegisterVariable(&r_bloom_brighten);
7213         Cvar_RegisterVariable(&r_bloom_blur);
7214         Cvar_RegisterVariable(&r_bloom_resolution);
7215         Cvar_RegisterVariable(&r_bloom_colorexponent);
7216         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7217         Cvar_RegisterVariable(&r_hdr);
7218         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7219         Cvar_RegisterVariable(&r_hdr_glowintensity);
7220         Cvar_RegisterVariable(&r_hdr_range);
7221         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7222         Cvar_RegisterVariable(&developer_texturelogging);
7223         Cvar_RegisterVariable(&gl_lightmaps);
7224         Cvar_RegisterVariable(&r_test);
7225         Cvar_RegisterVariable(&r_glsl_saturation);
7226         Cvar_RegisterVariable(&r_framedatasize);
7227         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7228                 Cvar_SetValue("r_fullbrights", 0);
7229         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7230
7231         Cvar_RegisterVariable(&r_track_sprites);
7232         Cvar_RegisterVariable(&r_track_sprites_flags);
7233         Cvar_RegisterVariable(&r_track_sprites_scalew);
7234         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7235         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7236         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7237 }
7238
7239 extern void R_Textures_Init(void);
7240 extern void GL_Draw_Init(void);
7241 extern void GL_Main_Init(void);
7242 extern void R_Shadow_Init(void);
7243 extern void R_Sky_Init(void);
7244 extern void GL_Surf_Init(void);
7245 extern void R_Particles_Init(void);
7246 extern void R_Explosion_Init(void);
7247 extern void gl_backend_init(void);
7248 extern void Sbar_Init(void);
7249 extern void R_LightningBeams_Init(void);
7250 extern void Mod_RenderInit(void);
7251 extern void Font_Init(void);
7252
7253 void Render_Init(void)
7254 {
7255         gl_backend_init();
7256         R_Textures_Init();
7257         GL_Main_Init();
7258         Font_Init();
7259         GL_Draw_Init();
7260         R_Shadow_Init();
7261         R_Sky_Init();
7262         GL_Surf_Init();
7263         Sbar_Init();
7264         R_Particles_Init();
7265         R_Explosion_Init();
7266         R_LightningBeams_Init();
7267         Mod_RenderInit();
7268 }
7269
7270 /*
7271 ===============
7272 GL_Init
7273 ===============
7274 */
7275 extern char *ENGINE_EXTENSIONS;
7276 void GL_Init (void)
7277 {
7278         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7279         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7280         gl_version = (const char *)qglGetString(GL_VERSION);
7281         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7282
7283         if (!gl_extensions)
7284                 gl_extensions = "";
7285         if (!gl_platformextensions)
7286                 gl_platformextensions = "";
7287
7288         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7289         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7290         Con_Printf("GL_VERSION: %s\n", gl_version);
7291         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7292         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7293
7294         VID_CheckExtensions();
7295
7296         // LordHavoc: report supported extensions
7297         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7298
7299         // clear to black (loading plaque will be seen over this)
7300         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7301 }
7302
7303 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7304 {
7305         int i;
7306         mplane_t *p;
7307         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7308         {
7309                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7310                 if (i == 4)
7311                         continue;
7312                 p = r_refdef.view.frustum + i;
7313                 switch(p->signbits)
7314                 {
7315                 default:
7316                 case 0:
7317                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7318                                 return true;
7319                         break;
7320                 case 1:
7321                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7322                                 return true;
7323                         break;
7324                 case 2:
7325                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7326                                 return true;
7327                         break;
7328                 case 3:
7329                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7330                                 return true;
7331                         break;
7332                 case 4:
7333                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7334                                 return true;
7335                         break;
7336                 case 5:
7337                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7338                                 return true;
7339                         break;
7340                 case 6:
7341                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7342                                 return true;
7343                         break;
7344                 case 7:
7345                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7346                                 return true;
7347                         break;
7348                 }
7349         }
7350         return false;
7351 }
7352
7353 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7354 {
7355         int i;
7356         const mplane_t *p;
7357         for (i = 0;i < numplanes;i++)
7358         {
7359                 p = planes + i;
7360                 switch(p->signbits)
7361                 {
7362                 default:
7363                 case 0:
7364                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7365                                 return true;
7366                         break;
7367                 case 1:
7368                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7369                                 return true;
7370                         break;
7371                 case 2:
7372                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7373                                 return true;
7374                         break;
7375                 case 3:
7376                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7377                                 return true;
7378                         break;
7379                 case 4:
7380                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7381                                 return true;
7382                         break;
7383                 case 5:
7384                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7385                                 return true;
7386                         break;
7387                 case 6:
7388                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7389                                 return true;
7390                         break;
7391                 case 7:
7392                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7393                                 return true;
7394                         break;
7395                 }
7396         }
7397         return false;
7398 }
7399
7400 //==================================================================================
7401
7402 // LordHavoc: this stores temporary data used within the same frame
7403
7404 qboolean r_framedata_failed;
7405 static size_t r_framedata_size;
7406 static size_t r_framedata_current;
7407 static void *r_framedata_base;
7408
7409 void R_FrameData_Reset(void)
7410 {
7411         if (r_framedata_base)
7412                 Mem_Free(r_framedata_base);
7413         r_framedata_base = NULL;
7414         r_framedata_size = 0;
7415         r_framedata_current = 0;
7416         r_framedata_failed = false;
7417 }
7418
7419 void R_FrameData_NewFrame(void)
7420 {
7421         size_t wantedsize;
7422         if (r_framedata_failed)
7423                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7424         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7425         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7426         if (r_framedata_size != wantedsize)
7427         {
7428                 r_framedata_size = wantedsize;
7429                 if (r_framedata_base)
7430                         Mem_Free(r_framedata_base);
7431                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7432         }
7433         r_framedata_current = 0;
7434         r_framedata_failed = false;
7435 }
7436
7437 void *R_FrameData_Alloc(size_t size)
7438 {
7439         void *data;
7440
7441         // align to 16 byte boundary
7442         size = (size + 15) & ~15;
7443         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7444         r_framedata_current += size;
7445
7446         // check overflow
7447         if (r_framedata_current > r_framedata_size)
7448                 r_framedata_failed = true;
7449
7450         // return NULL on everything after a failure
7451         if (r_framedata_failed)
7452                 return NULL;
7453
7454         return data;
7455 }
7456
7457 void *R_FrameData_Store(size_t size, void *data)
7458 {
7459         void *d = R_FrameData_Alloc(size);
7460         if (d)
7461                 memcpy(d, data, size);
7462         return d;
7463 }
7464
7465 //==================================================================================
7466
7467 // LordHavoc: animcache originally written by Echon, rewritten since then
7468
7469 /**
7470  * Animation cache prevents re-generating mesh data for an animated model
7471  * multiple times in one frame for lighting, shadowing, reflections, etc.
7472  */
7473
7474 void R_AnimCache_Free(void)
7475 {
7476 }
7477
7478 void R_AnimCache_ClearCache(void)
7479 {
7480         int i;
7481         entity_render_t *ent;
7482
7483         for (i = 0;i < r_refdef.scene.numentities;i++)
7484         {
7485                 ent = r_refdef.scene.entities[i];
7486                 ent->animcache_vertex3f = NULL;
7487                 ent->animcache_normal3f = NULL;
7488                 ent->animcache_svector3f = NULL;
7489                 ent->animcache_tvector3f = NULL;
7490                 ent->animcache_vertexposition = NULL;
7491                 ent->animcache_vertexmesh = NULL;
7492                 ent->animcache_vertexpositionbuffer = NULL;
7493                 ent->animcache_vertexmeshbuffer = NULL;
7494         }
7495 }
7496
7497 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7498 {
7499         int i;
7500
7501         // identical memory layout, so no need to allocate...
7502         // this also provides the vertexposition structure to everything, e.g.
7503         // depth masked rendering currently uses it even if having separate
7504         // arrays
7505         // NOTE: get rid of this optimization if changing it to e.g. 4f
7506         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7507
7508         // TODO:
7509         // get rid of following uses of VERTEXPOSITION, change to the array:
7510         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7511         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7512         // R_DrawTextureSurfaceList_DepthOnly
7513         // R_Q1BSP_DrawShadowMap
7514
7515         switch(vid.renderpath)
7516         {
7517         case RENDERPATH_GL20:
7518         case RENDERPATH_CGGL:
7519                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7520                 if (gl_mesh_separatearrays.integer)
7521                         return;
7522                 break;
7523         case RENDERPATH_D3D9:
7524         case RENDERPATH_D3D10:
7525         case RENDERPATH_D3D11:
7526                 // always need the meshbuffers
7527                 break;
7528         case RENDERPATH_GL13:
7529         case RENDERPATH_GL11:
7530                 // never need the meshbuffers
7531                 return;
7532         }
7533
7534         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7535                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7536         /*
7537         if (!ent->animcache_vertexposition)
7538                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7539         */
7540         if (ent->animcache_vertexposition)
7541         {
7542                 /*
7543                 for (i = 0;i < numvertices;i++)
7544                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7545                 */
7546                 // TODO: upload vertex buffer?
7547         }
7548         if (ent->animcache_vertexmesh)
7549         {
7550                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7551                 for (i = 0;i < numvertices;i++)
7552                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7553                 if (ent->animcache_svector3f)
7554                         for (i = 0;i < numvertices;i++)
7555                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7556                 if (ent->animcache_tvector3f)
7557                         for (i = 0;i < numvertices;i++)
7558                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7559                 if (ent->animcache_normal3f)
7560                         for (i = 0;i < numvertices;i++)
7561                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7562                 // TODO: upload vertex buffer?
7563         }
7564 }
7565
7566 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7567 {
7568         dp_model_t *model = ent->model;
7569         int numvertices;
7570         // see if it's already cached this frame
7571         if (ent->animcache_vertex3f)
7572         {
7573                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7574                 if (wantnormals || wanttangents)
7575                 {
7576                         if (ent->animcache_normal3f)
7577                                 wantnormals = false;
7578                         if (ent->animcache_svector3f)
7579                                 wanttangents = false;
7580                         if (wantnormals || wanttangents)
7581                         {
7582                                 numvertices = model->surfmesh.num_vertices;
7583                                 if (wantnormals)
7584                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7585                                 if (wanttangents)
7586                                 {
7587                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7588                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7589                                 }
7590                                 if (!r_framedata_failed)
7591                                 {
7592                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7593                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7594                                 }
7595                         }
7596                 }
7597         }
7598         else
7599         {
7600                 // see if this ent is worth caching
7601                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7602                         return false;
7603                 // get some memory for this entity and generate mesh data
7604                 numvertices = model->surfmesh.num_vertices;
7605                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7606                 if (wantnormals)
7607                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7608                 if (wanttangents)
7609                 {
7610                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7611                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7612                 }
7613                 if (!r_framedata_failed)
7614                 {
7615                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7616                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7617                 }
7618         }
7619         return !r_framedata_failed;
7620 }
7621
7622 void R_AnimCache_CacheVisibleEntities(void)
7623 {
7624         int i;
7625         qboolean wantnormals = true;
7626         qboolean wanttangents = !r_showsurfaces.integer;
7627
7628         switch(vid.renderpath)
7629         {
7630         case RENDERPATH_GL20:
7631         case RENDERPATH_CGGL:
7632         case RENDERPATH_D3D9:
7633         case RENDERPATH_D3D10:
7634         case RENDERPATH_D3D11:
7635                 break;
7636         case RENDERPATH_GL13:
7637         case RENDERPATH_GL11:
7638                 wanttangents = false;
7639                 break;
7640         }
7641
7642         if (r_shownormals.integer)
7643                 wanttangents = wantnormals = true;
7644
7645         // TODO: thread this
7646         // NOTE: R_PrepareRTLights() also caches entities
7647
7648         for (i = 0;i < r_refdef.scene.numentities;i++)
7649                 if (r_refdef.viewcache.entityvisible[i])
7650                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7651 }
7652
7653 //==================================================================================
7654
7655 static void R_View_UpdateEntityLighting (void)
7656 {
7657         int i;
7658         entity_render_t *ent;
7659         vec3_t tempdiffusenormal, avg;
7660         vec_t f, fa, fd, fdd;
7661         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7662
7663         for (i = 0;i < r_refdef.scene.numentities;i++)
7664         {
7665                 ent = r_refdef.scene.entities[i];
7666
7667                 // skip unseen models
7668                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7669                         continue;
7670
7671                 // skip bsp models
7672                 if (ent->model && ent->model->brush.num_leafs)
7673                 {
7674                         // TODO: use modellight for r_ambient settings on world?
7675                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7676                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7677                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7678                         continue;
7679                 }
7680
7681                 // fetch the lighting from the worldmodel data
7682                 VectorClear(ent->modellight_ambient);
7683                 VectorClear(ent->modellight_diffuse);
7684                 VectorClear(tempdiffusenormal);
7685                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7686                 {
7687                         vec3_t org;
7688                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7689                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7690                         if(ent->flags & RENDER_EQUALIZE)
7691                         {
7692                                 // first fix up ambient lighting...
7693                                 if(r_equalize_entities_minambient.value > 0)
7694                                 {
7695                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7696                                         if(fd > 0)
7697                                         {
7698                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7699                                                 if(fa < r_equalize_entities_minambient.value * fd)
7700                                                 {
7701                                                         // solve:
7702                                                         //   fa'/fd' = minambient
7703                                                         //   fa'+0.25*fd' = fa+0.25*fd
7704                                                         //   ...
7705                                                         //   fa' = fd' * minambient
7706                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7707                                                         //   ...
7708                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7709                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7710                                                         //   ...
7711                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7712                                                         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
7713                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7714                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7715                                                 }
7716                                         }
7717                                 }
7718
7719                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7720                                 {
7721                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7722                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7723                                         if(f > 0)
7724                                         {
7725                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7726                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7727                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7728                                         }
7729                                 }
7730                         }
7731                 }
7732                 else // highly rare
7733                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7734
7735                 // move the light direction into modelspace coordinates for lighting code
7736                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7737                 if(VectorLength2(ent->modellight_lightdir) == 0)
7738                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7739                 VectorNormalize(ent->modellight_lightdir);
7740         }
7741 }
7742
7743 #define MAX_LINEOFSIGHTTRACES 64
7744
7745 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7746 {
7747         int i;
7748         vec3_t boxmins, boxmaxs;
7749         vec3_t start;
7750         vec3_t end;
7751         dp_model_t *model = r_refdef.scene.worldmodel;
7752
7753         if (!model || !model->brush.TraceLineOfSight)
7754                 return true;
7755
7756         // expand the box a little
7757         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7758         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7759         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7760         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7761         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7762         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7763
7764         // return true if eye is inside enlarged box
7765         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7766                 return true;
7767
7768         // try center
7769         VectorCopy(eye, start);
7770         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7771         if (model->brush.TraceLineOfSight(model, start, end))
7772                 return true;
7773
7774         // try various random positions
7775         for (i = 0;i < numsamples;i++)
7776         {
7777                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7778                 if (model->brush.TraceLineOfSight(model, start, end))
7779                         return true;
7780         }
7781
7782         return false;
7783 }
7784
7785
7786 static void R_View_UpdateEntityVisible (void)
7787 {
7788         int i;
7789         int renderimask;
7790         int samples;
7791         entity_render_t *ent;
7792
7793         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7794                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7795                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7796                 :                                                          RENDER_EXTERIORMODEL;
7797         if (!r_drawviewmodel.integer)
7798                 renderimask |= RENDER_VIEWMODEL;
7799         if (!r_drawexteriormodel.integer)
7800                 renderimask |= RENDER_EXTERIORMODEL;
7801         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7802         {
7803                 // worldmodel can check visibility
7804                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7805                 for (i = 0;i < r_refdef.scene.numentities;i++)
7806                 {
7807                         ent = r_refdef.scene.entities[i];
7808                         if (!(ent->flags & renderimask))
7809                         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)))
7810                         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))
7811                                 r_refdef.viewcache.entityvisible[i] = true;
7812                 }
7813                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7814                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7815                 {
7816                         for (i = 0;i < r_refdef.scene.numentities;i++)
7817                         {
7818                                 ent = r_refdef.scene.entities[i];
7819                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7820                                 {
7821                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7822                                         if (samples < 0)
7823                                                 continue; // temp entities do pvs only
7824                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7825                                                 ent->last_trace_visibility = realtime;
7826                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7827                                                 r_refdef.viewcache.entityvisible[i] = 0;
7828                                 }
7829                         }
7830                 }
7831         }
7832         else
7833         {
7834                 // no worldmodel or it can't check visibility
7835                 for (i = 0;i < r_refdef.scene.numentities;i++)
7836                 {
7837                         ent = r_refdef.scene.entities[i];
7838                         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));
7839                 }
7840         }
7841 }
7842
7843 /// only used if skyrendermasked, and normally returns false
7844 int R_DrawBrushModelsSky (void)
7845 {
7846         int i, sky;
7847         entity_render_t *ent;
7848
7849         sky = false;
7850         for (i = 0;i < r_refdef.scene.numentities;i++)
7851         {
7852                 if (!r_refdef.viewcache.entityvisible[i])
7853                         continue;
7854                 ent = r_refdef.scene.entities[i];
7855                 if (!ent->model || !ent->model->DrawSky)
7856                         continue;
7857                 ent->model->DrawSky(ent);
7858                 sky = true;
7859         }
7860         return sky;
7861 }
7862
7863 static void R_DrawNoModel(entity_render_t *ent);
7864 static void R_DrawModels(void)
7865 {
7866         int i;
7867         entity_render_t *ent;
7868
7869         for (i = 0;i < r_refdef.scene.numentities;i++)
7870         {
7871                 if (!r_refdef.viewcache.entityvisible[i])
7872                         continue;
7873                 ent = r_refdef.scene.entities[i];
7874                 r_refdef.stats.entities++;
7875                 if (ent->model && ent->model->Draw != NULL)
7876                         ent->model->Draw(ent);
7877                 else
7878                         R_DrawNoModel(ent);
7879         }
7880 }
7881
7882 static void R_DrawModelsDepth(void)
7883 {
7884         int i;
7885         entity_render_t *ent;
7886
7887         for (i = 0;i < r_refdef.scene.numentities;i++)
7888         {
7889                 if (!r_refdef.viewcache.entityvisible[i])
7890                         continue;
7891                 ent = r_refdef.scene.entities[i];
7892                 if (ent->model && ent->model->DrawDepth != NULL)
7893                         ent->model->DrawDepth(ent);
7894         }
7895 }
7896
7897 static void R_DrawModelsDebug(void)
7898 {
7899         int i;
7900         entity_render_t *ent;
7901
7902         for (i = 0;i < r_refdef.scene.numentities;i++)
7903         {
7904                 if (!r_refdef.viewcache.entityvisible[i])
7905                         continue;
7906                 ent = r_refdef.scene.entities[i];
7907                 if (ent->model && ent->model->DrawDebug != NULL)
7908                         ent->model->DrawDebug(ent);
7909         }
7910 }
7911
7912 static void R_DrawModelsAddWaterPlanes(void)
7913 {
7914         int i;
7915         entity_render_t *ent;
7916
7917         for (i = 0;i < r_refdef.scene.numentities;i++)
7918         {
7919                 if (!r_refdef.viewcache.entityvisible[i])
7920                         continue;
7921                 ent = r_refdef.scene.entities[i];
7922                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7923                         ent->model->DrawAddWaterPlanes(ent);
7924         }
7925 }
7926
7927 static void R_View_SetFrustum(void)
7928 {
7929         int i;
7930         double slopex, slopey;
7931         vec3_t forward, left, up, origin;
7932
7933         // we can't trust r_refdef.view.forward and friends in reflected scenes
7934         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7935
7936 #if 0
7937         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7938         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7939         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7940         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7941         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7942         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7943         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7944         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7945         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7946         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7947         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7948         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7949 #endif
7950
7951 #if 0
7952         zNear = r_refdef.nearclip;
7953         nudge = 1.0 - 1.0 / (1<<23);
7954         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7955         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7956         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7957         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7958         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7959         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7960         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7961         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7962 #endif
7963
7964
7965
7966 #if 0
7967         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7968         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7969         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7970         r_refdef.view.frustum[0].dist = m[15] - m[12];
7971
7972         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7973         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7974         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7975         r_refdef.view.frustum[1].dist = m[15] + m[12];
7976
7977         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7978         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7979         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7980         r_refdef.view.frustum[2].dist = m[15] - m[13];
7981
7982         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7983         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7984         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7985         r_refdef.view.frustum[3].dist = m[15] + m[13];
7986
7987         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7988         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7989         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7990         r_refdef.view.frustum[4].dist = m[15] - m[14];
7991
7992         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7993         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7994         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7995         r_refdef.view.frustum[5].dist = m[15] + m[14];
7996 #endif
7997
7998         if (r_refdef.view.useperspective)
7999         {
8000                 slopex = 1.0 / r_refdef.view.frustum_x;
8001                 slopey = 1.0 / r_refdef.view.frustum_y;
8002                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8003                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8004                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8005                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8006                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8007
8008                 // Leaving those out was a mistake, those were in the old code, and they
8009                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8010                 // I couldn't reproduce it after adding those normalizations. --blub
8011                 VectorNormalize(r_refdef.view.frustum[0].normal);
8012                 VectorNormalize(r_refdef.view.frustum[1].normal);
8013                 VectorNormalize(r_refdef.view.frustum[2].normal);
8014                 VectorNormalize(r_refdef.view.frustum[3].normal);
8015
8016                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8017                 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]);
8018                 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]);
8019                 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]);
8020                 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]);
8021
8022                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8023                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8024                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8025                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8026                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8027         }
8028         else
8029         {
8030                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8031                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8032                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8033                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8034                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8035                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8036                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8037                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8038                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8039                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8040         }
8041         r_refdef.view.numfrustumplanes = 5;
8042
8043         if (r_refdef.view.useclipplane)
8044         {
8045                 r_refdef.view.numfrustumplanes = 6;
8046                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8047         }
8048
8049         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8050                 PlaneClassify(r_refdef.view.frustum + i);
8051
8052         // LordHavoc: note to all quake engine coders, Quake had a special case
8053         // for 90 degrees which assumed a square view (wrong), so I removed it,
8054         // Quake2 has it disabled as well.
8055
8056         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8057         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8058         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8059         //PlaneClassify(&frustum[0]);
8060
8061         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8062         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8063         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8064         //PlaneClassify(&frustum[1]);
8065
8066         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8067         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8068         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8069         //PlaneClassify(&frustum[2]);
8070
8071         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8072         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8073         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8074         //PlaneClassify(&frustum[3]);
8075
8076         // nearclip plane
8077         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8078         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8079         //PlaneClassify(&frustum[4]);
8080 }
8081
8082 void R_View_Update(void)
8083 {
8084         R_Main_ResizeViewCache();
8085         R_View_SetFrustum();
8086         R_View_WorldVisibility(r_refdef.view.useclipplane);
8087         R_View_UpdateEntityVisible();
8088         R_View_UpdateEntityLighting();
8089 }
8090
8091 void R_SetupView(qboolean allowwaterclippingplane)
8092 {
8093         const float *customclipplane = NULL;
8094         float plane[4];
8095         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8096         {
8097                 // LordHavoc: couldn't figure out how to make this approach the
8098                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8099                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8100                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8101                         dist = r_refdef.view.clipplane.dist;
8102                 plane[0] = r_refdef.view.clipplane.normal[0];
8103                 plane[1] = r_refdef.view.clipplane.normal[1];
8104                 plane[2] = r_refdef.view.clipplane.normal[2];
8105                 plane[3] = dist;
8106                 customclipplane = plane;
8107         }
8108
8109         if (!r_refdef.view.useperspective)
8110                 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);
8111         else if (vid.stencil && r_useinfinitefarclip.integer)
8112                 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);
8113         else
8114                 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);
8115         R_SetViewport(&r_refdef.view.viewport);
8116 }
8117
8118 void R_EntityMatrix(const matrix4x4_t *matrix)
8119 {
8120         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8121         {
8122                 gl_modelmatrixchanged = false;
8123                 gl_modelmatrix = *matrix;
8124                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8125                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8126                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8127                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8128                 CHECKGLERROR
8129                 switch(vid.renderpath)
8130                 {
8131                 case RENDERPATH_D3D9:
8132 #ifdef SUPPORTD3D
8133                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8134                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8135 #endif
8136                         break;
8137                 case RENDERPATH_D3D10:
8138                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8139                         break;
8140                 case RENDERPATH_D3D11:
8141                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8142                         break;
8143                 case RENDERPATH_GL20:
8144                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8145                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8146                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8147                         break;
8148                 case RENDERPATH_CGGL:
8149 #ifdef SUPPORTCG
8150                         CHECKCGERROR
8151                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8152                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8153                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8154 #endif
8155                         break;
8156                 case RENDERPATH_GL13:
8157                 case RENDERPATH_GL11:
8158                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8159                         break;
8160                 }
8161         }
8162 }
8163
8164 void R_ResetViewRendering2D(void)
8165 {
8166         r_viewport_t viewport;
8167         DrawQ_Finish();
8168
8169         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8170         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);
8171         R_SetViewport(&viewport);
8172         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8173         GL_Color(1, 1, 1, 1);
8174         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8175         GL_BlendFunc(GL_ONE, GL_ZERO);
8176         GL_AlphaTest(false);
8177         GL_ScissorTest(false);
8178         GL_DepthMask(false);
8179         GL_DepthRange(0, 1);
8180         GL_DepthTest(false);
8181         GL_DepthFunc(GL_LEQUAL);
8182         R_EntityMatrix(&identitymatrix);
8183         R_Mesh_ResetTextureState();
8184         GL_PolygonOffset(0, 0);
8185         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8186         switch(vid.renderpath)
8187         {
8188         case RENDERPATH_GL11:
8189         case RENDERPATH_GL13:
8190         case RENDERPATH_GL20:
8191         case RENDERPATH_CGGL:
8192                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8193                 break;
8194         case RENDERPATH_D3D9:
8195         case RENDERPATH_D3D10:
8196         case RENDERPATH_D3D11:
8197                 break;
8198         }
8199         GL_CullFace(GL_NONE);
8200 }
8201
8202 void R_ResetViewRendering3D(void)
8203 {
8204         DrawQ_Finish();
8205
8206         R_SetupView(true);
8207         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8208         GL_Color(1, 1, 1, 1);
8209         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8210         GL_BlendFunc(GL_ONE, GL_ZERO);
8211         GL_AlphaTest(false);
8212         GL_ScissorTest(true);
8213         GL_DepthMask(true);
8214         GL_DepthRange(0, 1);
8215         GL_DepthTest(true);
8216         GL_DepthFunc(GL_LEQUAL);
8217         R_EntityMatrix(&identitymatrix);
8218         R_Mesh_ResetTextureState();
8219         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8220         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8221         switch(vid.renderpath)
8222         {
8223         case RENDERPATH_GL11:
8224         case RENDERPATH_GL13:
8225         case RENDERPATH_GL20:
8226         case RENDERPATH_CGGL:
8227                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8228                 break;
8229         case RENDERPATH_D3D9:
8230         case RENDERPATH_D3D10:
8231         case RENDERPATH_D3D11:
8232                 break;
8233         }
8234         GL_CullFace(r_refdef.view.cullface_back);
8235 }
8236
8237 /*
8238 ================
8239 R_RenderView_UpdateViewVectors
8240 ================
8241 */
8242 static void R_RenderView_UpdateViewVectors(void)
8243 {
8244         // break apart the view matrix into vectors for various purposes
8245         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8246         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8247         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8248         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8249         // make an inverted copy of the view matrix for tracking sprites
8250         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8251 }
8252
8253 void R_RenderScene(void);
8254 void R_RenderWaterPlanes(void);
8255
8256 static void R_Water_StartFrame(void)
8257 {
8258         int i;
8259         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8260         r_waterstate_waterplane_t *p;
8261
8262         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8263                 return;
8264
8265         switch(vid.renderpath)
8266         {
8267         case RENDERPATH_GL20:
8268         case RENDERPATH_CGGL:
8269         case RENDERPATH_D3D9:
8270         case RENDERPATH_D3D10:
8271         case RENDERPATH_D3D11:
8272                 break;
8273         case RENDERPATH_GL13:
8274         case RENDERPATH_GL11:
8275                 return;
8276         }
8277
8278         // set waterwidth and waterheight to the water resolution that will be
8279         // used (often less than the screen resolution for faster rendering)
8280         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8281         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8282
8283         // calculate desired texture sizes
8284         // can't use water if the card does not support the texture size
8285         if (!r_water.integer || r_showsurfaces.integer)
8286                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8287         else if (vid.support.arb_texture_non_power_of_two)
8288         {
8289                 texturewidth = waterwidth;
8290                 textureheight = waterheight;
8291                 camerawidth = waterwidth;
8292                 cameraheight = waterheight;
8293         }
8294         else
8295         {
8296                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8297                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8298                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8299                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8300         }
8301
8302         // allocate textures as needed
8303         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8304         {
8305                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8306                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8307                 {
8308                         if (p->texture_refraction)
8309                                 R_FreeTexture(p->texture_refraction);
8310                         p->texture_refraction = NULL;
8311                         if (p->texture_reflection)
8312                                 R_FreeTexture(p->texture_reflection);
8313                         p->texture_reflection = NULL;
8314                         if (p->texture_camera)
8315                                 R_FreeTexture(p->texture_camera);
8316                         p->texture_camera = NULL;
8317                 }
8318                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8319                 r_waterstate.texturewidth = texturewidth;
8320                 r_waterstate.textureheight = textureheight;
8321                 r_waterstate.camerawidth = camerawidth;
8322                 r_waterstate.cameraheight = cameraheight;
8323         }
8324
8325         if (r_waterstate.texturewidth)
8326         {
8327                 r_waterstate.enabled = true;
8328
8329                 // when doing a reduced render (HDR) we want to use a smaller area
8330                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8331                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8332
8333                 // set up variables that will be used in shader setup
8334                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8335                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8336                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8337                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8338         }
8339
8340         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8341         r_waterstate.numwaterplanes = 0;
8342 }
8343
8344 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8345 {
8346         int triangleindex, planeindex;
8347         const int *e;
8348         vec3_t vert[3];
8349         vec3_t normal;
8350         vec3_t center;
8351         mplane_t plane;
8352         int cam_ent;
8353         r_waterstate_waterplane_t *p;
8354         texture_t *t = R_GetCurrentTexture(surface->texture);
8355         cam_ent = t->camera_entity;
8356         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8357                 cam_ent = 0;
8358
8359         // just use the first triangle with a valid normal for any decisions
8360         VectorClear(normal);
8361         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8362         {
8363                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8364                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8365                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8366                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8367                 if (VectorLength2(normal) >= 0.001)
8368                         break;
8369         }
8370
8371         VectorCopy(normal, plane.normal);
8372         VectorNormalize(plane.normal);
8373         plane.dist = DotProduct(vert[0], plane.normal);
8374         PlaneClassify(&plane);
8375         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8376         {
8377                 // skip backfaces (except if nocullface is set)
8378                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8379                         return;
8380                 VectorNegate(plane.normal, plane.normal);
8381                 plane.dist *= -1;
8382                 PlaneClassify(&plane);
8383         }
8384
8385
8386         // find a matching plane if there is one
8387         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8388                 if(p->camera_entity == t->camera_entity)
8389                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8390                                 break;
8391         if (planeindex >= r_waterstate.maxwaterplanes)
8392                 return; // nothing we can do, out of planes
8393
8394         // if this triangle does not fit any known plane rendered this frame, add one
8395         if (planeindex >= r_waterstate.numwaterplanes)
8396         {
8397                 // store the new plane
8398                 r_waterstate.numwaterplanes++;
8399                 p->plane = plane;
8400                 // clear materialflags and pvs
8401                 p->materialflags = 0;
8402                 p->pvsvalid = false;
8403                 p->camera_entity = t->camera_entity;
8404         }
8405         // merge this surface's materialflags into the waterplane
8406         p->materialflags |= t->currentmaterialflags;
8407         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8408         {
8409                 // merge this surface's PVS into the waterplane
8410                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8411                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8412                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8413                 {
8414                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8415                         p->pvsvalid = true;
8416                 }
8417         }
8418 }
8419
8420 static void R_Water_ProcessPlanes(void)
8421 {
8422         r_refdef_view_t originalview;
8423         r_refdef_view_t myview;
8424         int planeindex;
8425         r_waterstate_waterplane_t *p;
8426         vec3_t visorigin;
8427
8428         originalview = r_refdef.view;
8429
8430         // make sure enough textures are allocated
8431         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8432         {
8433                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8434                 {
8435                         if (!p->texture_refraction)
8436                                 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);
8437                         if (!p->texture_refraction)
8438                                 goto error;
8439                 }
8440                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8441                 {
8442                         if (!p->texture_camera)
8443                                 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);
8444                         if (!p->texture_camera)
8445                                 goto error;
8446                 }
8447
8448                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8449                 {
8450                         if (!p->texture_reflection)
8451                                 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);
8452                         if (!p->texture_reflection)
8453                                 goto error;
8454                 }
8455         }
8456
8457         // render views
8458         r_refdef.view = originalview;
8459         r_refdef.view.showdebug = false;
8460         r_refdef.view.width = r_waterstate.waterwidth;
8461         r_refdef.view.height = r_waterstate.waterheight;
8462         r_refdef.view.useclipplane = true;
8463         myview = r_refdef.view;
8464         r_waterstate.renderingscene = true;
8465         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8466         {
8467                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8468                 {
8469                         r_refdef.view = myview;
8470                         // render reflected scene and copy into texture
8471                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8472                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8473                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8474                         r_refdef.view.clipplane = p->plane;
8475                         // reverse the cullface settings for this render
8476                         r_refdef.view.cullface_front = GL_FRONT;
8477                         r_refdef.view.cullface_back = GL_BACK;
8478                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8479                         {
8480                                 r_refdef.view.usecustompvs = true;
8481                                 if (p->pvsvalid)
8482                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8483                                 else
8484                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8485                         }
8486
8487                         R_ResetViewRendering3D();
8488                         R_ClearScreen(r_refdef.fogenabled);
8489                         R_View_Update();
8490                         R_RenderScene();
8491
8492                         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);
8493                 }
8494
8495                 // render the normal view scene and copy into texture
8496                 // (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)
8497                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8498                 {
8499                         r_waterstate.renderingrefraction = true;
8500                         r_refdef.view = myview;
8501
8502                         r_refdef.view.clipplane = p->plane;
8503                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8504                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8505
8506                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8507                         {
8508                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8509                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8510                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8511                                 R_RenderView_UpdateViewVectors();
8512                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8513                                 {
8514                                         r_refdef.view.usecustompvs = true;
8515                                         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);
8516                                 }
8517                         }
8518
8519                         PlaneClassify(&r_refdef.view.clipplane);
8520
8521                         R_ResetViewRendering3D();
8522                         R_ClearScreen(r_refdef.fogenabled);
8523                         R_View_Update();
8524                         R_RenderScene();
8525
8526                         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);
8527                         r_waterstate.renderingrefraction = false;
8528                 }
8529                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8530                 {
8531                         r_refdef.view = myview;
8532
8533                         r_refdef.view.clipplane = p->plane;
8534                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8535                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8536
8537                         r_refdef.view.width = r_waterstate.camerawidth;
8538                         r_refdef.view.height = r_waterstate.cameraheight;
8539                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8540                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8541
8542                         if(p->camera_entity)
8543                         {
8544                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8545                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8546                         }
8547
8548                         // reverse the cullface settings for this render
8549                         r_refdef.view.cullface_front = GL_FRONT;
8550                         r_refdef.view.cullface_back = GL_BACK;
8551                         // also reverse the view matrix
8552                         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
8553                         R_RenderView_UpdateViewVectors();
8554                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8555                         {
8556                                 r_refdef.view.usecustompvs = true;
8557                                 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);
8558                         }
8559                         
8560                         // camera needs no clipplane
8561                         r_refdef.view.useclipplane = false;
8562
8563                         PlaneClassify(&r_refdef.view.clipplane);
8564
8565                         R_ResetViewRendering3D();
8566                         R_ClearScreen(r_refdef.fogenabled);
8567                         R_View_Update();
8568                         R_RenderScene();
8569
8570                         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);
8571                         r_waterstate.renderingrefraction = false;
8572                 }
8573
8574         }
8575         r_waterstate.renderingscene = false;
8576         r_refdef.view = originalview;
8577         R_ResetViewRendering3D();
8578         R_ClearScreen(r_refdef.fogenabled);
8579         R_View_Update();
8580         return;
8581 error:
8582         r_refdef.view = originalview;
8583         r_waterstate.renderingscene = false;
8584         Cvar_SetValueQuick(&r_water, 0);
8585         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8586         return;
8587 }
8588
8589 void R_Bloom_StartFrame(void)
8590 {
8591         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8592
8593         switch(vid.renderpath)
8594         {
8595         case RENDERPATH_GL20:
8596         case RENDERPATH_CGGL:
8597         case RENDERPATH_D3D9:
8598         case RENDERPATH_D3D10:
8599         case RENDERPATH_D3D11:
8600                 break;
8601         case RENDERPATH_GL13:
8602         case RENDERPATH_GL11:
8603                 return;
8604         }
8605
8606         // set bloomwidth and bloomheight to the bloom resolution that will be
8607         // used (often less than the screen resolution for faster rendering)
8608         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8609         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8610         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8611         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8612         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8613
8614         // calculate desired texture sizes
8615         if (vid.support.arb_texture_non_power_of_two)
8616         {
8617                 screentexturewidth = r_refdef.view.width;
8618                 screentextureheight = r_refdef.view.height;
8619                 bloomtexturewidth = r_bloomstate.bloomwidth;
8620                 bloomtextureheight = r_bloomstate.bloomheight;
8621         }
8622         else
8623         {
8624                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8625                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8626                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8627                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8628         }
8629
8630         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))
8631         {
8632                 Cvar_SetValueQuick(&r_hdr, 0);
8633                 Cvar_SetValueQuick(&r_bloom, 0);
8634                 Cvar_SetValueQuick(&r_motionblur, 0);
8635                 Cvar_SetValueQuick(&r_damageblur, 0);
8636         }
8637
8638         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)))
8639                 screentexturewidth = screentextureheight = 0;
8640         if (!r_hdr.integer && !r_bloom.integer)
8641                 bloomtexturewidth = bloomtextureheight = 0;
8642
8643         // allocate textures as needed
8644         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8645         {
8646                 if (r_bloomstate.texture_screen)
8647                         R_FreeTexture(r_bloomstate.texture_screen);
8648                 r_bloomstate.texture_screen = NULL;
8649                 r_bloomstate.screentexturewidth = screentexturewidth;
8650                 r_bloomstate.screentextureheight = screentextureheight;
8651                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8652                         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);
8653         }
8654         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8655         {
8656                 if (r_bloomstate.texture_bloom)
8657                         R_FreeTexture(r_bloomstate.texture_bloom);
8658                 r_bloomstate.texture_bloom = NULL;
8659                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8660                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8661                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8662                         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);
8663         }
8664
8665         // when doing a reduced render (HDR) we want to use a smaller area
8666         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8667         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8668         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8669         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8670         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8671
8672         // set up a texcoord array for the full resolution screen image
8673         // (we have to keep this around to copy back during final render)
8674         r_bloomstate.screentexcoord2f[0] = 0;
8675         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8676         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8677         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8678         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8679         r_bloomstate.screentexcoord2f[5] = 0;
8680         r_bloomstate.screentexcoord2f[6] = 0;
8681         r_bloomstate.screentexcoord2f[7] = 0;
8682
8683         // set up a texcoord array for the reduced resolution bloom image
8684         // (which will be additive blended over the screen image)
8685         r_bloomstate.bloomtexcoord2f[0] = 0;
8686         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8687         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8688         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8689         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8690         r_bloomstate.bloomtexcoord2f[5] = 0;
8691         r_bloomstate.bloomtexcoord2f[6] = 0;
8692         r_bloomstate.bloomtexcoord2f[7] = 0;
8693
8694         switch(vid.renderpath)
8695         {
8696         case RENDERPATH_GL11:
8697         case RENDERPATH_GL13:
8698         case RENDERPATH_GL20:
8699         case RENDERPATH_CGGL:
8700                 break;
8701         case RENDERPATH_D3D9:
8702         case RENDERPATH_D3D10:
8703         case RENDERPATH_D3D11:
8704                 {
8705                         int i;
8706                         for (i = 0;i < 4;i++)
8707                         {
8708                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8709                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8710                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8711                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8712                         }
8713                 }
8714                 break;
8715         }
8716
8717         if (r_hdr.integer || r_bloom.integer)
8718         {
8719                 r_bloomstate.enabled = true;
8720                 r_bloomstate.hdr = r_hdr.integer != 0;
8721         }
8722
8723         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);
8724 }
8725
8726 void R_Bloom_CopyBloomTexture(float colorscale)
8727 {
8728         r_refdef.stats.bloom++;
8729
8730         // scale down screen texture to the bloom texture size
8731         CHECKGLERROR
8732         R_SetViewport(&r_bloomstate.viewport);
8733         GL_BlendFunc(GL_ONE, GL_ZERO);
8734         GL_Color(colorscale, colorscale, colorscale, 1);
8735         // 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...
8736         switch(vid.renderpath)
8737         {
8738         case RENDERPATH_GL11:
8739         case RENDERPATH_GL13:
8740         case RENDERPATH_GL20:
8741         case RENDERPATH_CGGL:
8742                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8743                 break;
8744         case RENDERPATH_D3D9:
8745         case RENDERPATH_D3D10:
8746         case RENDERPATH_D3D11:
8747                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8748                 break;
8749         }
8750         // TODO: do boxfilter scale-down in shader?
8751         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8752         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8753         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8754
8755         // we now have a bloom image in the framebuffer
8756         // copy it into the bloom image texture for later processing
8757         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);
8758         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8759 }
8760
8761 void R_Bloom_CopyHDRTexture(void)
8762 {
8763         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);
8764         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8765 }
8766
8767 void R_Bloom_MakeTexture(void)
8768 {
8769         int x, range, dir;
8770         float xoffset, yoffset, r, brighten;
8771
8772         r_refdef.stats.bloom++;
8773
8774         R_ResetViewRendering2D();
8775
8776         // we have a bloom image in the framebuffer
8777         CHECKGLERROR
8778         R_SetViewport(&r_bloomstate.viewport);
8779
8780         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8781         {
8782                 x *= 2;
8783                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8784                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8785                 GL_Color(r,r,r,1);
8786                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8787                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8788                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8789                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8790
8791                 // copy the vertically blurred bloom view to a texture
8792                 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);
8793                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8794         }
8795
8796         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8797         brighten = r_bloom_brighten.value;
8798         if (r_hdr.integer)
8799                 brighten *= r_hdr_range.value;
8800         brighten = sqrt(brighten);
8801         if(range >= 1)
8802                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8803         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8804
8805         for (dir = 0;dir < 2;dir++)
8806         {
8807                 // blend on at multiple vertical offsets to achieve a vertical blur
8808                 // TODO: do offset blends using GLSL
8809                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8810                 GL_BlendFunc(GL_ONE, GL_ZERO);
8811                 for (x = -range;x <= range;x++)
8812                 {
8813                         if (!dir){xoffset = 0;yoffset = x;}
8814                         else {xoffset = x;yoffset = 0;}
8815                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8816                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8817                         // compute a texcoord array with the specified x and y offset
8818                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8819                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8820                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8821                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8822                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8823                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8824                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8825                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8826                         // this r value looks like a 'dot' particle, fading sharply to
8827                         // black at the edges
8828                         // (probably not realistic but looks good enough)
8829                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8830                         //r = brighten/(range*2+1);
8831                         r = brighten / (range * 2 + 1);
8832                         if(range >= 1)
8833                                 r *= (1 - x*x/(float)(range*range));
8834                         GL_Color(r, r, r, 1);
8835                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8836                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8837                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8838                         GL_BlendFunc(GL_ONE, GL_ONE);
8839                 }
8840
8841                 // copy the vertically blurred bloom view to a texture
8842                 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);
8843                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8844         }
8845 }
8846
8847 void R_HDR_RenderBloomTexture(void)
8848 {
8849         int oldwidth, oldheight;
8850         float oldcolorscale;
8851
8852         oldcolorscale = r_refdef.view.colorscale;
8853         oldwidth = r_refdef.view.width;
8854         oldheight = r_refdef.view.height;
8855         r_refdef.view.width = r_bloomstate.bloomwidth;
8856         r_refdef.view.height = r_bloomstate.bloomheight;
8857
8858         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8859         // TODO: add exposure compensation features
8860         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8861
8862         r_refdef.view.showdebug = false;
8863         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8864
8865         R_ResetViewRendering3D();
8866
8867         R_ClearScreen(r_refdef.fogenabled);
8868         if (r_timereport_active)
8869                 R_TimeReport("HDRclear");
8870
8871         R_View_Update();
8872         if (r_timereport_active)
8873                 R_TimeReport("visibility");
8874
8875         // only do secondary renders with HDR if r_hdr is 2 or higher
8876         r_waterstate.numwaterplanes = 0;
8877         if (r_waterstate.enabled && r_hdr.integer >= 2)
8878                 R_RenderWaterPlanes();
8879
8880         r_refdef.view.showdebug = true;
8881         R_RenderScene();
8882         r_waterstate.numwaterplanes = 0;
8883
8884         R_ResetViewRendering2D();
8885
8886         R_Bloom_CopyHDRTexture();
8887         R_Bloom_MakeTexture();
8888
8889         // restore the view settings
8890         r_refdef.view.width = oldwidth;
8891         r_refdef.view.height = oldheight;
8892         r_refdef.view.colorscale = oldcolorscale;
8893
8894         R_ResetViewRendering3D();
8895
8896         R_ClearScreen(r_refdef.fogenabled);
8897         if (r_timereport_active)
8898                 R_TimeReport("viewclear");
8899 }
8900
8901 static void R_BlendView(void)
8902 {
8903         unsigned int permutation;
8904         float uservecs[4][4];
8905
8906         switch (vid.renderpath)
8907         {
8908         case RENDERPATH_GL20:
8909         case RENDERPATH_CGGL:
8910         case RENDERPATH_D3D9:
8911         case RENDERPATH_D3D10:
8912         case RENDERPATH_D3D11:
8913                 permutation =
8914                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8915                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8916                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8917                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8918                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8919
8920                 if (r_bloomstate.texture_screen)
8921                 {
8922                         // make sure the buffer is available
8923                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8924
8925                         R_ResetViewRendering2D();
8926
8927                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8928                         {
8929                                 // declare variables
8930                                 float speed;
8931                                 static float avgspeed;
8932
8933                                 speed = VectorLength(cl.movement_velocity);
8934
8935                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8936                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8937
8938                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8939                                 speed = bound(0, speed, 1);
8940                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8941
8942                                 // calculate values into a standard alpha
8943                                 cl.motionbluralpha = 1 - exp(-
8944                                                 (
8945                                                  (r_motionblur.value * speed / 80)
8946                                                  +
8947                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8948                                                 )
8949                                                 /
8950                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8951                                            );
8952
8953                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8954                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8955                                 // apply the blur
8956                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8957                                 {
8958                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8959                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8960                                         switch(vid.renderpath)
8961                                         {
8962                                         case RENDERPATH_GL11:
8963                                         case RENDERPATH_GL13:
8964                                         case RENDERPATH_GL20:
8965                                         case RENDERPATH_CGGL:
8966                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8967                                                 break;
8968                                         case RENDERPATH_D3D9:
8969                                         case RENDERPATH_D3D10:
8970                                         case RENDERPATH_D3D11:
8971                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8972                                                 break;
8973                                         }
8974                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8975                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8976                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8977                                 }
8978                         }
8979
8980                         // copy view into the screen texture
8981                         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);
8982                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8983                 }
8984                 else if (!r_bloomstate.texture_bloom)
8985                 {
8986                         // we may still have to do view tint...
8987                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8988                         {
8989                                 // apply a color tint to the whole view
8990                                 R_ResetViewRendering2D();
8991                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8992                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8993                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8994                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8995                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8996                         }
8997                         break; // no screen processing, no bloom, skip it
8998                 }
8999
9000                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9001                 {
9002                         // render simple bloom effect
9003                         // copy the screen and shrink it and darken it for the bloom process
9004                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9005                         // make the bloom texture
9006                         R_Bloom_MakeTexture();
9007                 }
9008
9009 #if _MSC_VER >= 1400
9010 #define sscanf sscanf_s
9011 #endif
9012                 memset(uservecs, 0, sizeof(uservecs));
9013                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9014                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9015                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9016                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9017
9018                 R_ResetViewRendering2D();
9019                 GL_Color(1, 1, 1, 1);
9020                 GL_BlendFunc(GL_ONE, GL_ZERO);
9021
9022                 switch(vid.renderpath)
9023                 {
9024                 case RENDERPATH_GL20:
9025                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9026                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9027                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9028                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9029                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9030                         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]);
9031                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9032                         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]);
9033                         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]);
9034                         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]);
9035                         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]);
9036                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9037                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9038                         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);
9039                         break;
9040                 case RENDERPATH_CGGL:
9041 #ifdef SUPPORTCG
9042                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9043                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9044                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9045                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9046                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9047                         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
9048                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9049                         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
9050                         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
9051                         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
9052                         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
9053                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9054                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9055                         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);
9056 #endif
9057                         break;
9058                 case RENDERPATH_D3D9:
9059 #ifdef SUPPORTD3D
9060                         // 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...
9061                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9062                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9063                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9064                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9065                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9066                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9067                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9068                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9069                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9070                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9071                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9072                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9073                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9074                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9075 #endif
9076                         break;
9077                 case RENDERPATH_D3D10:
9078                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9079                         break;
9080                 case RENDERPATH_D3D11:
9081                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9082                         break;
9083                 default:
9084                         break;
9085                 }
9086                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9087                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9088                 break;
9089         case RENDERPATH_GL13:
9090         case RENDERPATH_GL11:
9091                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9092                 {
9093                         // apply a color tint to the whole view
9094                         R_ResetViewRendering2D();
9095                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9096                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9097                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9098                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9099                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9100                 }
9101                 break;
9102         }
9103 }
9104
9105 matrix4x4_t r_waterscrollmatrix;
9106
9107 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9108 {
9109         if (r_refdef.fog_density)
9110         {
9111                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9112                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9113                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9114
9115                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9116                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9117                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9118                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9119
9120                 {
9121                         vec3_t fogvec;
9122                         VectorCopy(r_refdef.fogcolor, fogvec);
9123                         //   color.rgb *= ContrastBoost * SceneBrightness;
9124                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9125                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9126                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9127                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9128                 }
9129         }
9130 }
9131
9132 void R_UpdateVariables(void)
9133 {
9134         R_Textures_Frame();
9135
9136         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9137
9138         r_refdef.farclip = r_farclip_base.value;
9139         if (r_refdef.scene.worldmodel)
9140                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9141         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9142
9143         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9144                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9145         r_refdef.polygonfactor = 0;
9146         r_refdef.polygonoffset = 0;
9147         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9148         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9149
9150         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9151         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9152         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9153         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9154         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9155         if (r_showsurfaces.integer)
9156         {
9157                 r_refdef.scene.rtworld = false;
9158                 r_refdef.scene.rtworldshadows = false;
9159                 r_refdef.scene.rtdlight = false;
9160                 r_refdef.scene.rtdlightshadows = false;
9161                 r_refdef.lightmapintensity = 0;
9162         }
9163
9164         if (gamemode == GAME_NEHAHRA)
9165         {
9166                 if (gl_fogenable.integer)
9167                 {
9168                         r_refdef.oldgl_fogenable = true;
9169                         r_refdef.fog_density = gl_fogdensity.value;
9170                         r_refdef.fog_red = gl_fogred.value;
9171                         r_refdef.fog_green = gl_foggreen.value;
9172                         r_refdef.fog_blue = gl_fogblue.value;
9173                         r_refdef.fog_alpha = 1;
9174                         r_refdef.fog_start = 0;
9175                         r_refdef.fog_end = gl_skyclip.value;
9176                         r_refdef.fog_height = 1<<30;
9177                         r_refdef.fog_fadedepth = 128;
9178                 }
9179                 else if (r_refdef.oldgl_fogenable)
9180                 {
9181                         r_refdef.oldgl_fogenable = false;
9182                         r_refdef.fog_density = 0;
9183                         r_refdef.fog_red = 0;
9184                         r_refdef.fog_green = 0;
9185                         r_refdef.fog_blue = 0;
9186                         r_refdef.fog_alpha = 0;
9187                         r_refdef.fog_start = 0;
9188                         r_refdef.fog_end = 0;
9189                         r_refdef.fog_height = 1<<30;
9190                         r_refdef.fog_fadedepth = 128;
9191                 }
9192         }
9193
9194         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9195         r_refdef.fog_start = max(0, r_refdef.fog_start);
9196         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9197
9198         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9199
9200         if (r_refdef.fog_density && r_drawfog.integer)
9201         {
9202                 r_refdef.fogenabled = true;
9203                 // this is the point where the fog reaches 0.9986 alpha, which we
9204                 // consider a good enough cutoff point for the texture
9205                 // (0.9986 * 256 == 255.6)
9206                 if (r_fog_exp2.integer)
9207                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9208                 else
9209                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9210                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9211                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9212                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9213                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9214                         R_BuildFogHeightTexture();
9215                 // fog color was already set
9216                 // update the fog texture
9217                 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)
9218                         R_BuildFogTexture();
9219                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9220                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9221         }
9222         else
9223                 r_refdef.fogenabled = false;
9224
9225         switch(vid.renderpath)
9226         {
9227         case RENDERPATH_GL20:
9228         case RENDERPATH_CGGL:
9229         case RENDERPATH_D3D9:
9230         case RENDERPATH_D3D10:
9231         case RENDERPATH_D3D11:
9232                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9233                 {
9234                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9235                         {
9236                                 // build GLSL gamma texture
9237 #define RAMPWIDTH 256
9238                                 unsigned short ramp[RAMPWIDTH * 3];
9239                                 unsigned char rampbgr[RAMPWIDTH][4];
9240                                 int i;
9241
9242                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9243
9244                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9245                                 for(i = 0; i < RAMPWIDTH; ++i)
9246                                 {
9247                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9248                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9249                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9250                                         rampbgr[i][3] = 0;
9251                                 }
9252                                 if (r_texture_gammaramps)
9253                                 {
9254                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9255                                 }
9256                                 else
9257                                 {
9258                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9259                                 }
9260                         }
9261                 }
9262                 else
9263                 {
9264                         // remove GLSL gamma texture
9265                 }
9266                 break;
9267         case RENDERPATH_GL13:
9268         case RENDERPATH_GL11:
9269                 break;
9270         }
9271 }
9272
9273 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9274 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9275 /*
9276 ================
9277 R_SelectScene
9278 ================
9279 */
9280 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9281         if( scenetype != r_currentscenetype ) {
9282                 // store the old scenetype
9283                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9284                 r_currentscenetype = scenetype;
9285                 // move in the new scene
9286                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9287         }
9288 }
9289
9290 /*
9291 ================
9292 R_GetScenePointer
9293 ================
9294 */
9295 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9296 {
9297         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9298         if( scenetype == r_currentscenetype ) {
9299                 return &r_refdef.scene;
9300         } else {
9301                 return &r_scenes_store[ scenetype ];
9302         }
9303 }
9304
9305 /*
9306 ================
9307 R_RenderView
9308 ================
9309 */
9310 void R_RenderView(void)
9311 {
9312         if (r_timereport_active)
9313                 R_TimeReport("start");
9314         r_textureframe++; // used only by R_GetCurrentTexture
9315         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9316
9317         if (!r_drawentities.integer)
9318                 r_refdef.scene.numentities = 0;
9319
9320         R_AnimCache_ClearCache();
9321         R_FrameData_NewFrame();
9322
9323         if (r_refdef.view.isoverlay)
9324         {
9325                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9326                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9327                 R_TimeReport("depthclear");
9328
9329                 r_refdef.view.showdebug = false;
9330
9331                 r_waterstate.enabled = false;
9332                 r_waterstate.numwaterplanes = 0;
9333
9334                 R_RenderScene();
9335
9336                 CHECKGLERROR
9337                 return;
9338         }
9339
9340         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9341                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9342
9343         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9344
9345         R_RenderView_UpdateViewVectors();
9346
9347         R_Shadow_UpdateWorldLightSelection();
9348
9349         R_Bloom_StartFrame();
9350         R_Water_StartFrame();
9351
9352         CHECKGLERROR
9353         if (r_timereport_active)
9354                 R_TimeReport("viewsetup");
9355
9356         R_ResetViewRendering3D();
9357
9358         if (r_refdef.view.clear || r_refdef.fogenabled)
9359         {
9360                 R_ClearScreen(r_refdef.fogenabled);
9361                 if (r_timereport_active)
9362                         R_TimeReport("viewclear");
9363         }
9364         r_refdef.view.clear = true;
9365
9366         // this produces a bloom texture to be used in R_BlendView() later
9367         if (r_hdr.integer && r_bloomstate.bloomwidth)
9368         {
9369                 R_HDR_RenderBloomTexture();
9370                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9371                 r_textureframe++; // used only by R_GetCurrentTexture
9372         }
9373
9374         r_refdef.view.showdebug = true;
9375
9376         R_View_Update();
9377         if (r_timereport_active)
9378                 R_TimeReport("visibility");
9379
9380         r_waterstate.numwaterplanes = 0;
9381         if (r_waterstate.enabled)
9382                 R_RenderWaterPlanes();
9383
9384         R_RenderScene();
9385         r_waterstate.numwaterplanes = 0;
9386
9387         R_BlendView();
9388         if (r_timereport_active)
9389                 R_TimeReport("blendview");
9390
9391         GL_Scissor(0, 0, vid.width, vid.height);
9392         GL_ScissorTest(false);
9393         CHECKGLERROR
9394 }
9395
9396 void R_RenderWaterPlanes(void)
9397 {
9398         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9399         {
9400                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9401                 if (r_timereport_active)
9402                         R_TimeReport("waterworld");
9403         }
9404
9405         // don't let sound skip if going slow
9406         if (r_refdef.scene.extraupdate)
9407                 S_ExtraUpdate ();
9408
9409         R_DrawModelsAddWaterPlanes();
9410         if (r_timereport_active)
9411                 R_TimeReport("watermodels");
9412
9413         if (r_waterstate.numwaterplanes)
9414         {
9415                 R_Water_ProcessPlanes();
9416                 if (r_timereport_active)
9417                         R_TimeReport("waterscenes");
9418         }
9419 }
9420
9421 extern void R_DrawLightningBeams (void);
9422 extern void VM_CL_AddPolygonsToMeshQueue (void);
9423 extern void R_DrawPortals (void);
9424 extern cvar_t cl_locs_show;
9425 static void R_DrawLocs(void);
9426 static void R_DrawEntityBBoxes(void);
9427 static void R_DrawModelDecals(void);
9428 extern void R_DrawModelShadows(void);
9429 extern void R_DrawModelShadowMaps(void);
9430 extern cvar_t cl_decals_newsystem;
9431 extern qboolean r_shadow_usingdeferredprepass;
9432 void R_RenderScene(void)
9433 {
9434         qboolean shadowmapping = false;
9435
9436         if (r_timereport_active)
9437                 R_TimeReport("beginscene");
9438
9439         r_refdef.stats.renders++;
9440
9441         R_UpdateFogColor();
9442
9443         // don't let sound skip if going slow
9444         if (r_refdef.scene.extraupdate)
9445                 S_ExtraUpdate ();
9446
9447         R_MeshQueue_BeginScene();
9448
9449         R_SkyStartFrame();
9450
9451         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);
9452
9453         if (r_timereport_active)
9454                 R_TimeReport("skystartframe");
9455
9456         if (cl.csqc_vidvars.drawworld)
9457         {
9458                 // don't let sound skip if going slow
9459                 if (r_refdef.scene.extraupdate)
9460                         S_ExtraUpdate ();
9461
9462                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9463                 {
9464                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9465                         if (r_timereport_active)
9466                                 R_TimeReport("worldsky");
9467                 }
9468
9469                 if (R_DrawBrushModelsSky() && r_timereport_active)
9470                         R_TimeReport("bmodelsky");
9471
9472                 if (skyrendermasked && skyrenderlater)
9473                 {
9474                         // we have to force off the water clipping plane while rendering sky
9475                         R_SetupView(false);
9476                         R_Sky();
9477                         R_SetupView(true);
9478                         if (r_timereport_active)
9479                                 R_TimeReport("sky");
9480                 }
9481         }
9482
9483         R_AnimCache_CacheVisibleEntities();
9484         if (r_timereport_active)
9485                 R_TimeReport("animation");
9486
9487         R_Shadow_PrepareLights();
9488         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9489                 R_Shadow_PrepareModelShadows();
9490         if (r_timereport_active)
9491                 R_TimeReport("preparelights");
9492
9493         if (R_Shadow_ShadowMappingEnabled())
9494                 shadowmapping = true;
9495
9496         if (r_shadow_usingdeferredprepass)
9497                 R_Shadow_DrawPrepass();
9498
9499         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9500         {
9501                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9502                 if (r_timereport_active)
9503                         R_TimeReport("worlddepth");
9504         }
9505         if (r_depthfirst.integer >= 2)
9506         {
9507                 R_DrawModelsDepth();
9508                 if (r_timereport_active)
9509                         R_TimeReport("modeldepth");
9510         }
9511
9512         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9513         {
9514                 R_DrawModelShadowMaps();
9515                 R_ResetViewRendering3D();
9516                 // don't let sound skip if going slow
9517                 if (r_refdef.scene.extraupdate)
9518                         S_ExtraUpdate ();
9519         }
9520
9521         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9522         {
9523                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9524                 if (r_timereport_active)
9525                         R_TimeReport("world");
9526         }
9527
9528         // don't let sound skip if going slow
9529         if (r_refdef.scene.extraupdate)
9530                 S_ExtraUpdate ();
9531
9532         R_DrawModels();
9533         if (r_timereport_active)
9534                 R_TimeReport("models");
9535
9536         // don't let sound skip if going slow
9537         if (r_refdef.scene.extraupdate)
9538                 S_ExtraUpdate ();
9539
9540         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9541         {
9542                 R_DrawModelShadows();
9543                 R_ResetViewRendering3D();
9544                 // don't let sound skip if going slow
9545                 if (r_refdef.scene.extraupdate)
9546                         S_ExtraUpdate ();
9547         }
9548
9549         if (!r_shadow_usingdeferredprepass)
9550         {
9551                 R_Shadow_DrawLights();
9552                 if (r_timereport_active)
9553                         R_TimeReport("rtlights");
9554         }
9555
9556         // don't let sound skip if going slow
9557         if (r_refdef.scene.extraupdate)
9558                 S_ExtraUpdate ();
9559
9560         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9561         {
9562                 R_DrawModelShadows();
9563                 R_ResetViewRendering3D();
9564                 // don't let sound skip if going slow
9565                 if (r_refdef.scene.extraupdate)
9566                         S_ExtraUpdate ();
9567         }
9568
9569         if (cl.csqc_vidvars.drawworld)
9570         {
9571                 if (cl_decals_newsystem.integer)
9572                 {
9573                         R_DrawModelDecals();
9574                         if (r_timereport_active)
9575                                 R_TimeReport("modeldecals");
9576                 }
9577                 else
9578                 {
9579                         R_DrawDecals();
9580                         if (r_timereport_active)
9581                                 R_TimeReport("decals");
9582                 }
9583
9584                 R_DrawParticles();
9585                 if (r_timereport_active)
9586                         R_TimeReport("particles");
9587
9588                 R_DrawExplosions();
9589                 if (r_timereport_active)
9590                         R_TimeReport("explosions");
9591
9592                 R_DrawLightningBeams();
9593                 if (r_timereport_active)
9594                         R_TimeReport("lightning");
9595         }
9596
9597         VM_CL_AddPolygonsToMeshQueue();
9598
9599         if (r_refdef.view.showdebug)
9600         {
9601                 if (cl_locs_show.integer)
9602                 {
9603                         R_DrawLocs();
9604                         if (r_timereport_active)
9605                                 R_TimeReport("showlocs");
9606                 }
9607
9608                 if (r_drawportals.integer)
9609                 {
9610                         R_DrawPortals();
9611                         if (r_timereport_active)
9612                                 R_TimeReport("portals");
9613                 }
9614
9615                 if (r_showbboxes.value > 0)
9616                 {
9617                         R_DrawEntityBBoxes();
9618                         if (r_timereport_active)
9619                                 R_TimeReport("bboxes");
9620                 }
9621         }
9622
9623         R_MeshQueue_RenderTransparent();
9624         if (r_timereport_active)
9625                 R_TimeReport("drawtrans");
9626
9627         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))
9628         {
9629                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9630                 if (r_timereport_active)
9631                         R_TimeReport("worlddebug");
9632                 R_DrawModelsDebug();
9633                 if (r_timereport_active)
9634                         R_TimeReport("modeldebug");
9635         }
9636
9637         if (cl.csqc_vidvars.drawworld)
9638         {
9639                 R_Shadow_DrawCoronas();
9640                 if (r_timereport_active)
9641                         R_TimeReport("coronas");
9642         }
9643
9644         // don't let sound skip if going slow
9645         if (r_refdef.scene.extraupdate)
9646                 S_ExtraUpdate ();
9647
9648         R_ResetViewRendering2D();
9649 }
9650
9651 static const unsigned short bboxelements[36] =
9652 {
9653         5, 1, 3, 5, 3, 7,
9654         6, 2, 0, 6, 0, 4,
9655         7, 3, 2, 7, 2, 6,
9656         4, 0, 1, 4, 1, 5,
9657         4, 5, 7, 4, 7, 6,
9658         1, 0, 2, 1, 2, 3,
9659 };
9660
9661 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9662 {
9663         int i;
9664         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9665
9666         RSurf_ActiveWorldEntity();
9667
9668         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9669         GL_DepthMask(false);
9670         GL_DepthRange(0, 1);
9671         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9672         R_Mesh_ResetTextureState();
9673
9674         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9675         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9676         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9677         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9678         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9679         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9680         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9681         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9682         R_FillColors(color4f, 8, cr, cg, cb, ca);
9683         if (r_refdef.fogenabled)
9684         {
9685                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9686                 {
9687                         f1 = RSurf_FogVertex(v);
9688                         f2 = 1 - f1;
9689                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9690                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9691                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9692                 }
9693         }
9694         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9695         R_Mesh_ResetTextureState();
9696         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9697         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9698 }
9699
9700 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9701 {
9702         int i;
9703         float color[4];
9704         prvm_edict_t *edict;
9705         prvm_prog_t *prog_save = prog;
9706
9707         // this function draws bounding boxes of server entities
9708         if (!sv.active)
9709                 return;
9710
9711         GL_CullFace(GL_NONE);
9712         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9713
9714         prog = 0;
9715         SV_VM_Begin();
9716         for (i = 0;i < numsurfaces;i++)
9717         {
9718                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9719                 switch ((int)edict->fields.server->solid)
9720                 {
9721                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9722                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9723                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9724                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9725                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9726                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9727                 }
9728                 color[3] *= r_showbboxes.value;
9729                 color[3] = bound(0, color[3], 1);
9730                 GL_DepthTest(!r_showdisabledepthtest.integer);
9731                 GL_CullFace(r_refdef.view.cullface_front);
9732                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9733         }
9734         SV_VM_End();
9735         prog = prog_save;
9736 }
9737
9738 static void R_DrawEntityBBoxes(void)
9739 {
9740         int i;
9741         prvm_edict_t *edict;
9742         vec3_t center;
9743         prvm_prog_t *prog_save = prog;
9744
9745         // this function draws bounding boxes of server entities
9746         if (!sv.active)
9747                 return;
9748
9749         prog = 0;
9750         SV_VM_Begin();
9751         for (i = 0;i < prog->num_edicts;i++)
9752         {
9753                 edict = PRVM_EDICT_NUM(i);
9754                 if (edict->priv.server->free)
9755                         continue;
9756                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9757                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9758                         continue;
9759                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9760                         continue;
9761                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9762                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9763         }
9764         SV_VM_End();
9765         prog = prog_save;
9766 }
9767
9768 static const int nomodelelement3i[24] =
9769 {
9770         5, 2, 0,
9771         5, 1, 2,
9772         5, 0, 3,
9773         5, 3, 1,
9774         0, 2, 4,
9775         2, 1, 4,
9776         3, 0, 4,
9777         1, 3, 4
9778 };
9779
9780 static const unsigned short nomodelelement3s[24] =
9781 {
9782         5, 2, 0,
9783         5, 1, 2,
9784         5, 0, 3,
9785         5, 3, 1,
9786         0, 2, 4,
9787         2, 1, 4,
9788         3, 0, 4,
9789         1, 3, 4
9790 };
9791
9792 static const float nomodelvertex3f[6*3] =
9793 {
9794         -16,   0,   0,
9795          16,   0,   0,
9796           0, -16,   0,
9797           0,  16,   0,
9798           0,   0, -16,
9799           0,   0,  16
9800 };
9801
9802 static const float nomodelcolor4f[6*4] =
9803 {
9804         0.0f, 0.0f, 0.5f, 1.0f,
9805         0.0f, 0.0f, 0.5f, 1.0f,
9806         0.0f, 0.5f, 0.0f, 1.0f,
9807         0.0f, 0.5f, 0.0f, 1.0f,
9808         0.5f, 0.0f, 0.0f, 1.0f,
9809         0.5f, 0.0f, 0.0f, 1.0f
9810 };
9811
9812 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9813 {
9814         int i;
9815         float f1, f2, *c;
9816         float color4f[6*4];
9817
9818         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);
9819
9820         // this is only called once per entity so numsurfaces is always 1, and
9821         // surfacelist is always {0}, so this code does not handle batches
9822
9823         if (rsurface.ent_flags & RENDER_ADDITIVE)
9824         {
9825                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9826                 GL_DepthMask(false);
9827         }
9828         else if (rsurface.colormod[3] < 1)
9829         {
9830                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9831                 GL_DepthMask(false);
9832         }
9833         else
9834         {
9835                 GL_BlendFunc(GL_ONE, GL_ZERO);
9836                 GL_DepthMask(true);
9837         }
9838         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9839         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9840         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9841         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9842         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9843         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9844         for (i = 0, c = color4f;i < 6;i++, c += 4)
9845         {
9846                 c[0] *= rsurface.colormod[0];
9847                 c[1] *= rsurface.colormod[1];
9848                 c[2] *= rsurface.colormod[2];
9849                 c[3] *= rsurface.colormod[3];
9850         }
9851         if (r_refdef.fogenabled)
9852         {
9853                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9854                 {
9855                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9856                         f2 = 1 - f1;
9857                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9858                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9859                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9860                 }
9861         }
9862         R_Mesh_ResetTextureState();
9863         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9864         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9865 }
9866
9867 void R_DrawNoModel(entity_render_t *ent)
9868 {
9869         vec3_t org;
9870         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9871         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9872                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9873         else
9874                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9875 }
9876
9877 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9878 {
9879         vec3_t right1, right2, diff, normal;
9880
9881         VectorSubtract (org2, org1, normal);
9882
9883         // calculate 'right' vector for start
9884         VectorSubtract (r_refdef.view.origin, org1, diff);
9885         CrossProduct (normal, diff, right1);
9886         VectorNormalize (right1);
9887
9888         // calculate 'right' vector for end
9889         VectorSubtract (r_refdef.view.origin, org2, diff);
9890         CrossProduct (normal, diff, right2);
9891         VectorNormalize (right2);
9892
9893         vert[ 0] = org1[0] + width * right1[0];
9894         vert[ 1] = org1[1] + width * right1[1];
9895         vert[ 2] = org1[2] + width * right1[2];
9896         vert[ 3] = org1[0] - width * right1[0];
9897         vert[ 4] = org1[1] - width * right1[1];
9898         vert[ 5] = org1[2] - width * right1[2];
9899         vert[ 6] = org2[0] - width * right2[0];
9900         vert[ 7] = org2[1] - width * right2[1];
9901         vert[ 8] = org2[2] - width * right2[2];
9902         vert[ 9] = org2[0] + width * right2[0];
9903         vert[10] = org2[1] + width * right2[1];
9904         vert[11] = org2[2] + width * right2[2];
9905 }
9906
9907 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)
9908 {
9909         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9910         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9911         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9912         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9913         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9914         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9915         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9916         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9917         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9918         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9919         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9920         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9921 }
9922
9923 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9924 {
9925         int i;
9926         float *vertex3f;
9927         float v[3];
9928         VectorSet(v, x, y, z);
9929         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9930                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9931                         break;
9932         if (i == mesh->numvertices)
9933         {
9934                 if (mesh->numvertices < mesh->maxvertices)
9935                 {
9936                         VectorCopy(v, vertex3f);
9937                         mesh->numvertices++;
9938                 }
9939                 return mesh->numvertices;
9940         }
9941         else
9942                 return i;
9943 }
9944
9945 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9946 {
9947         int i;
9948         int *e, element[3];
9949         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9950         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9951         e = mesh->element3i + mesh->numtriangles * 3;
9952         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9953         {
9954                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9955                 if (mesh->numtriangles < mesh->maxtriangles)
9956                 {
9957                         *e++ = element[0];
9958                         *e++ = element[1];
9959                         *e++ = element[2];
9960                         mesh->numtriangles++;
9961                 }
9962                 element[1] = element[2];
9963         }
9964 }
9965
9966 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9967 {
9968         int i;
9969         int *e, element[3];
9970         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9971         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9972         e = mesh->element3i + mesh->numtriangles * 3;
9973         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9974         {
9975                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9976                 if (mesh->numtriangles < mesh->maxtriangles)
9977                 {
9978                         *e++ = element[0];
9979                         *e++ = element[1];
9980                         *e++ = element[2];
9981                         mesh->numtriangles++;
9982                 }
9983                 element[1] = element[2];
9984         }
9985 }
9986
9987 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9988 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9989 {
9990         int planenum, planenum2;
9991         int w;
9992         int tempnumpoints;
9993         mplane_t *plane, *plane2;
9994         double maxdist;
9995         double temppoints[2][256*3];
9996         // figure out how large a bounding box we need to properly compute this brush
9997         maxdist = 0;
9998         for (w = 0;w < numplanes;w++)
9999                 maxdist = max(maxdist, fabs(planes[w].dist));
10000         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10001         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10002         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10003         {
10004                 w = 0;
10005                 tempnumpoints = 4;
10006                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10007                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10008                 {
10009                         if (planenum2 == planenum)
10010                                 continue;
10011                         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);
10012                         w = !w;
10013                 }
10014                 if (tempnumpoints < 3)
10015                         continue;
10016                 // generate elements forming a triangle fan for this polygon
10017                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10018         }
10019 }
10020
10021 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)
10022 {
10023         texturelayer_t *layer;
10024         layer = t->currentlayers + t->currentnumlayers++;
10025         layer->type = type;
10026         layer->depthmask = depthmask;
10027         layer->blendfunc1 = blendfunc1;
10028         layer->blendfunc2 = blendfunc2;
10029         layer->texture = texture;
10030         layer->texmatrix = *matrix;
10031         layer->color[0] = r;
10032         layer->color[1] = g;
10033         layer->color[2] = b;
10034         layer->color[3] = a;
10035 }
10036
10037 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10038 {
10039         if(parms[0] == 0 && parms[1] == 0)
10040                 return false;
10041         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10042                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10043                         return false;
10044         return true;
10045 }
10046
10047 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10048 {
10049         double index, f;
10050         index = parms[2] + r_refdef.scene.time * parms[3];
10051         index -= floor(index);
10052         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10053         {
10054         default:
10055         case Q3WAVEFUNC_NONE:
10056         case Q3WAVEFUNC_NOISE:
10057         case Q3WAVEFUNC_COUNT:
10058                 f = 0;
10059                 break;
10060         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10061         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10062         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10063         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10064         case Q3WAVEFUNC_TRIANGLE:
10065                 index *= 4;
10066                 f = index - floor(index);
10067                 if (index < 1)
10068                         f = f;
10069                 else if (index < 2)
10070                         f = 1 - f;
10071                 else if (index < 3)
10072                         f = -f;
10073                 else
10074                         f = -(1 - f);
10075                 break;
10076         }
10077         f = parms[0] + parms[1] * f;
10078         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10079                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10080         return (float) f;
10081 }
10082
10083 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10084 {
10085         int w, h, idx;
10086         float f;
10087         float tcmat[12];
10088         matrix4x4_t matrix, temp;
10089         switch(tcmod->tcmod)
10090         {
10091                 case Q3TCMOD_COUNT:
10092                 case Q3TCMOD_NONE:
10093                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10094                                 matrix = r_waterscrollmatrix;
10095                         else
10096                                 matrix = identitymatrix;
10097                         break;
10098                 case Q3TCMOD_ENTITYTRANSLATE:
10099                         // this is used in Q3 to allow the gamecode to control texcoord
10100                         // scrolling on the entity, which is not supported in darkplaces yet.
10101                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10102                         break;
10103                 case Q3TCMOD_ROTATE:
10104                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10105                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10106                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10107                         break;
10108                 case Q3TCMOD_SCALE:
10109                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10110                         break;
10111                 case Q3TCMOD_SCROLL:
10112                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10113                         break;
10114                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10115                         w = (int) tcmod->parms[0];
10116                         h = (int) tcmod->parms[1];
10117                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10118                         f = f - floor(f);
10119                         idx = (int) floor(f * w * h);
10120                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10121                         break;
10122                 case Q3TCMOD_STRETCH:
10123                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10124                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10125                         break;
10126                 case Q3TCMOD_TRANSFORM:
10127                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10128                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10129                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10130                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10131                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10132                         break;
10133                 case Q3TCMOD_TURBULENT:
10134                         // this is handled in the RSurf_PrepareVertices function
10135                         matrix = identitymatrix;
10136                         break;
10137         }
10138         temp = *texmatrix;
10139         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10140 }
10141
10142 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10143 {
10144         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10145         char name[MAX_QPATH];
10146         skinframe_t *skinframe;
10147         unsigned char pixels[296*194];
10148         strlcpy(cache->name, skinname, sizeof(cache->name));
10149         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10150         if (developer_loading.integer)
10151                 Con_Printf("loading %s\n", name);
10152         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10153         if (!skinframe || !skinframe->base)
10154         {
10155                 unsigned char *f;
10156                 fs_offset_t filesize;
10157                 skinframe = NULL;
10158                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10159                 if (f)
10160                 {
10161                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10162                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10163                         Mem_Free(f);
10164                 }
10165         }
10166         cache->skinframe = skinframe;
10167 }
10168
10169 texture_t *R_GetCurrentTexture(texture_t *t)
10170 {
10171         int i;
10172         const entity_render_t *ent = rsurface.entity;
10173         dp_model_t *model = ent->model;
10174         q3shaderinfo_layer_tcmod_t *tcmod;
10175
10176         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10177                 return t->currentframe;
10178         t->update_lastrenderframe = r_textureframe;
10179         t->update_lastrenderentity = (void *)ent;
10180
10181         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10182                 t->camera_entity = ent->entitynumber;
10183         else
10184                 t->camera_entity = 0;
10185
10186         // switch to an alternate material if this is a q1bsp animated material
10187         {
10188                 texture_t *texture = t;
10189                 int s = rsurface.ent_skinnum;
10190                 if ((unsigned int)s >= (unsigned int)model->numskins)
10191                         s = 0;
10192                 if (model->skinscenes)
10193                 {
10194                         if (model->skinscenes[s].framecount > 1)
10195                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10196                         else
10197                                 s = model->skinscenes[s].firstframe;
10198                 }
10199                 if (s > 0)
10200                         t = t + s * model->num_surfaces;
10201                 if (t->animated)
10202                 {
10203                         // use an alternate animation if the entity's frame is not 0,
10204                         // and only if the texture has an alternate animation
10205                         if (rsurface.ent_alttextures && t->anim_total[1])
10206                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10207                         else
10208                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10209                 }
10210                 texture->currentframe = t;
10211         }
10212
10213         // update currentskinframe to be a qw skin or animation frame
10214         if (rsurface.ent_qwskin >= 0)
10215         {
10216                 i = rsurface.ent_qwskin;
10217                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10218                 {
10219                         r_qwskincache_size = cl.maxclients;
10220                         if (r_qwskincache)
10221                                 Mem_Free(r_qwskincache);
10222                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10223                 }
10224                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10225                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10226                 t->currentskinframe = r_qwskincache[i].skinframe;
10227                 if (t->currentskinframe == NULL)
10228                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10229         }
10230         else if (t->numskinframes >= 2)
10231                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10232         if (t->backgroundnumskinframes >= 2)
10233                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10234
10235         t->currentmaterialflags = t->basematerialflags;
10236         t->currentalpha = rsurface.colormod[3];
10237         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10238                 t->currentalpha *= r_wateralpha.value;
10239         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10240                 t->currentalpha *= t->r_water_wateralpha;
10241         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10242                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10243         if (!(rsurface.ent_flags & RENDER_LIGHT))
10244                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10245         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10246         {
10247                 // pick a model lighting mode
10248                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10249                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10250                 else
10251                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10252         }
10253         if (rsurface.ent_flags & RENDER_ADDITIVE)
10254                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10255         else if (t->currentalpha < 1)
10256                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10257         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10258                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10259         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10260                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10261         if (t->backgroundnumskinframes)
10262                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10263         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10264         {
10265                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10266                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10267         }
10268         else
10269                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10270         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10271                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10272
10273         // there is no tcmod
10274         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10275         {
10276                 t->currenttexmatrix = r_waterscrollmatrix;
10277                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10278         }
10279         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10280         {
10281                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10282                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10283         }
10284
10285         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10286                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10287         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10288                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10289
10290         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10291         if (t->currentskinframe->qpixels)
10292                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10293         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10294         if (!t->basetexture)
10295                 t->basetexture = r_texture_notexture;
10296         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10297         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10298         t->nmaptexture = t->currentskinframe->nmap;
10299         if (!t->nmaptexture)
10300                 t->nmaptexture = r_texture_blanknormalmap;
10301         t->glosstexture = r_texture_black;
10302         t->glowtexture = t->currentskinframe->glow;
10303         t->fogtexture = t->currentskinframe->fog;
10304         t->reflectmasktexture = t->currentskinframe->reflect;
10305         if (t->backgroundnumskinframes)
10306         {
10307                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10308                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10309                 t->backgroundglosstexture = r_texture_black;
10310                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10311                 if (!t->backgroundnmaptexture)
10312                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10313         }
10314         else
10315         {
10316                 t->backgroundbasetexture = r_texture_white;
10317                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10318                 t->backgroundglosstexture = r_texture_black;
10319                 t->backgroundglowtexture = NULL;
10320         }
10321         t->specularpower = r_shadow_glossexponent.value;
10322         // TODO: store reference values for these in the texture?
10323         t->specularscale = 0;
10324         if (r_shadow_gloss.integer > 0)
10325         {
10326                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10327                 {
10328                         if (r_shadow_glossintensity.value > 0)
10329                         {
10330                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10331                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10332                                 t->specularscale = r_shadow_glossintensity.value;
10333                         }
10334                 }
10335                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10336                 {
10337                         t->glosstexture = r_texture_white;
10338                         t->backgroundglosstexture = r_texture_white;
10339                         t->specularscale = r_shadow_gloss2intensity.value;
10340                         t->specularpower = r_shadow_gloss2exponent.value;
10341                 }
10342         }
10343         t->specularscale *= t->specularscalemod;
10344         t->specularpower *= t->specularpowermod;
10345
10346         // lightmaps mode looks bad with dlights using actual texturing, so turn
10347         // off the colormap and glossmap, but leave the normalmap on as it still
10348         // accurately represents the shading involved
10349         if (gl_lightmaps.integer)
10350         {
10351                 t->basetexture = r_texture_grey128;
10352                 t->pantstexture = r_texture_black;
10353                 t->shirttexture = r_texture_black;
10354                 t->nmaptexture = r_texture_blanknormalmap;
10355                 t->glosstexture = r_texture_black;
10356                 t->glowtexture = NULL;
10357                 t->fogtexture = NULL;
10358                 t->reflectmasktexture = NULL;
10359                 t->backgroundbasetexture = NULL;
10360                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10361                 t->backgroundglosstexture = r_texture_black;
10362                 t->backgroundglowtexture = NULL;
10363                 t->specularscale = 0;
10364                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10365         }
10366
10367         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10368         VectorClear(t->dlightcolor);
10369         t->currentnumlayers = 0;
10370         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10371         {
10372                 int blendfunc1, blendfunc2;
10373                 qboolean depthmask;
10374                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10375                 {
10376                         blendfunc1 = GL_SRC_ALPHA;
10377                         blendfunc2 = GL_ONE;
10378                 }
10379                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10380                 {
10381                         blendfunc1 = GL_SRC_ALPHA;
10382                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10383                 }
10384                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10385                 {
10386                         blendfunc1 = t->customblendfunc[0];
10387                         blendfunc2 = t->customblendfunc[1];
10388                 }
10389                 else
10390                 {
10391                         blendfunc1 = GL_ONE;
10392                         blendfunc2 = GL_ZERO;
10393                 }
10394                 // don't colormod evilblend textures
10395                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10396                         VectorSet(t->lightmapcolor, 1, 1, 1);
10397                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10398                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10399                 {
10400                         // fullbright is not affected by r_refdef.lightmapintensity
10401                         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]);
10402                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10403                                 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]);
10404                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10405                                 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]);
10406                 }
10407                 else
10408                 {
10409                         vec3_t ambientcolor;
10410                         float colorscale;
10411                         // set the color tint used for lights affecting this surface
10412                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10413                         colorscale = 2;
10414                         // q3bsp has no lightmap updates, so the lightstylevalue that
10415                         // would normally be baked into the lightmap must be
10416                         // applied to the color
10417                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10418                         if (model->type == mod_brushq3)
10419                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10420                         colorscale *= r_refdef.lightmapintensity;
10421                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10422                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10423                         // basic lit geometry
10424                         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]);
10425                         // add pants/shirt if needed
10426                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10427                                 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]);
10428                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10429                                 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]);
10430                         // now add ambient passes if needed
10431                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10432                         {
10433                                 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]);
10434                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10435                                         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]);
10436                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10437                                         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]);
10438                         }
10439                 }
10440                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10441                         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]);
10442                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10443                 {
10444                         // if this is opaque use alpha blend which will darken the earlier
10445                         // passes cheaply.
10446                         //
10447                         // if this is an alpha blended material, all the earlier passes
10448                         // were darkened by fog already, so we only need to add the fog
10449                         // color ontop through the fog mask texture
10450                         //
10451                         // if this is an additive blended material, all the earlier passes
10452                         // were darkened by fog already, and we should not add fog color
10453                         // (because the background was not darkened, there is no fog color
10454                         // that was lost behind it).
10455                         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]);
10456                 }
10457         }
10458
10459         return t->currentframe;
10460 }
10461
10462 rsurfacestate_t rsurface;
10463
10464 void R_Mesh_ResizeArrays(int newvertices)
10465 {
10466         unsigned char *base;
10467         size_t size;
10468         if (rsurface.array_size >= newvertices)
10469                 return;
10470         if (rsurface.array_base)
10471                 Mem_Free(rsurface.array_base);
10472         rsurface.array_size = (newvertices + 1023) & ~1023;
10473         size = 0;
10474         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10475         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10476         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10477         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10478         size += rsurface.array_size * sizeof(float[3]);
10479         size += rsurface.array_size * sizeof(float[3]);
10480         size += rsurface.array_size * sizeof(float[3]);
10481         size += rsurface.array_size * sizeof(float[3]);
10482         size += rsurface.array_size * sizeof(float[3]);
10483         size += rsurface.array_size * sizeof(float[3]);
10484         size += rsurface.array_size * sizeof(float[3]);
10485         size += rsurface.array_size * sizeof(float[3]);
10486         size += rsurface.array_size * sizeof(float[4]);
10487         size += rsurface.array_size * sizeof(float[2]);
10488         size += rsurface.array_size * sizeof(float[2]);
10489         size += rsurface.array_size * sizeof(float[4]);
10490         size += rsurface.array_size * sizeof(int[3]);
10491         size += rsurface.array_size * sizeof(unsigned short[3]);
10492         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10493         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10494         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10495         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10496         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10497         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10498         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10499         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10500         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10501         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10502         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10503         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10504         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10505         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10506         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10507         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10508         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10509         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10510         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10511 }
10512
10513 void RSurf_ActiveWorldEntity(void)
10514 {
10515         dp_model_t *model = r_refdef.scene.worldmodel;
10516         //if (rsurface.entity == r_refdef.scene.worldentity)
10517         //      return;
10518         rsurface.entity = r_refdef.scene.worldentity;
10519         rsurface.skeleton = NULL;
10520         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10521         rsurface.ent_skinnum = 0;
10522         rsurface.ent_qwskin = -1;
10523         rsurface.ent_shadertime = 0;
10524         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10525         if (rsurface.array_size < model->surfmesh.num_vertices)
10526                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10527         rsurface.matrix = identitymatrix;
10528         rsurface.inversematrix = identitymatrix;
10529         rsurface.matrixscale = 1;
10530         rsurface.inversematrixscale = 1;
10531         R_EntityMatrix(&identitymatrix);
10532         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10533         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10534         rsurface.fograngerecip = r_refdef.fograngerecip;
10535         rsurface.fogheightfade = r_refdef.fogheightfade;
10536         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10537         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10538         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10539         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10540         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10541         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10542         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10543         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10544         rsurface.colormod[3] = 1;
10545         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);
10546         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10547         rsurface.frameblend[0].lerp = 1;
10548         rsurface.ent_alttextures = false;
10549         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10550         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10551         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10552         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10553         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10554         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10555         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10556         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10557         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10558         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10559         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10560         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10561         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10562         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10563         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10564         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10565         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10566         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10567         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10568         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10569         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10570         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10571         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10572         rsurface.modelelement3i = model->surfmesh.data_element3i;
10573         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10574         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10575         rsurface.modelelement3s = model->surfmesh.data_element3s;
10576         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10577         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10578         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10579         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10580         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10581         rsurface.modelsurfaces = model->data_surfaces;
10582         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10583         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10584         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10585         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10586         rsurface.modelgeneratedvertex = false;
10587         rsurface.batchgeneratedvertex = false;
10588         rsurface.batchfirstvertex = 0;
10589         rsurface.batchnumvertices = 0;
10590         rsurface.batchfirsttriangle = 0;
10591         rsurface.batchnumtriangles = 0;
10592         rsurface.batchvertex3f  = NULL;
10593         rsurface.batchvertex3f_vertexbuffer = NULL;
10594         rsurface.batchvertex3f_bufferoffset = 0;
10595         rsurface.batchsvector3f = NULL;
10596         rsurface.batchsvector3f_vertexbuffer = NULL;
10597         rsurface.batchsvector3f_bufferoffset = 0;
10598         rsurface.batchtvector3f = NULL;
10599         rsurface.batchtvector3f_vertexbuffer = NULL;
10600         rsurface.batchtvector3f_bufferoffset = 0;
10601         rsurface.batchnormal3f  = NULL;
10602         rsurface.batchnormal3f_vertexbuffer = NULL;
10603         rsurface.batchnormal3f_bufferoffset = 0;
10604         rsurface.batchlightmapcolor4f = NULL;
10605         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10606         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10607         rsurface.batchtexcoordtexture2f = NULL;
10608         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10609         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10610         rsurface.batchtexcoordlightmap2f = NULL;
10611         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10612         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10613         rsurface.batchvertexmesh = NULL;
10614         rsurface.batchvertexmeshbuffer = NULL;
10615         rsurface.batchvertexposition = NULL;
10616         rsurface.batchvertexpositionbuffer = NULL;
10617         rsurface.batchelement3i = NULL;
10618         rsurface.batchelement3i_indexbuffer = NULL;
10619         rsurface.batchelement3i_bufferoffset = 0;
10620         rsurface.batchelement3s = NULL;
10621         rsurface.batchelement3s_indexbuffer = NULL;
10622         rsurface.batchelement3s_bufferoffset = 0;
10623         rsurface.passcolor4f = NULL;
10624         rsurface.passcolor4f_vertexbuffer = NULL;
10625         rsurface.passcolor4f_bufferoffset = 0;
10626 }
10627
10628 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10629 {
10630         dp_model_t *model = ent->model;
10631         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10632         //      return;
10633         rsurface.entity = (entity_render_t *)ent;
10634         rsurface.skeleton = ent->skeleton;
10635         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10636         rsurface.ent_skinnum = ent->skinnum;
10637         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;
10638         rsurface.ent_shadertime = ent->shadertime;
10639         rsurface.ent_flags = ent->flags;
10640         if (rsurface.array_size < model->surfmesh.num_vertices)
10641                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10642         rsurface.matrix = ent->matrix;
10643         rsurface.inversematrix = ent->inversematrix;
10644         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10645         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10646         R_EntityMatrix(&rsurface.matrix);
10647         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10648         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10649         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10650         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10651         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10652         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10653         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10654         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10655         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10656         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10657         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10658         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10659         rsurface.colormod[3] = ent->alpha;
10660         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10661         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10662         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10663         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10664         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10665         if (ent->model->brush.submodel && !prepass)
10666         {
10667                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10668                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10669         }
10670         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10671         {
10672                 if (ent->animcache_vertex3f && !r_framedata_failed)
10673                 {
10674                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10675                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10676                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10677                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10678                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10679                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10680                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10681                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10682                 }
10683                 else if (wanttangents)
10684                 {
10685                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10686                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10687                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10688                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10689                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10690                         rsurface.modelvertexmesh = NULL;
10691                         rsurface.modelvertexmeshbuffer = NULL;
10692                         rsurface.modelvertexposition = NULL;
10693                         rsurface.modelvertexpositionbuffer = NULL;
10694                 }
10695                 else if (wantnormals)
10696                 {
10697                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10698                         rsurface.modelsvector3f = NULL;
10699                         rsurface.modeltvector3f = NULL;
10700                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10701                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10702                         rsurface.modelvertexmesh = NULL;
10703                         rsurface.modelvertexmeshbuffer = NULL;
10704                         rsurface.modelvertexposition = NULL;
10705                         rsurface.modelvertexpositionbuffer = NULL;
10706                 }
10707                 else
10708                 {
10709                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10710                         rsurface.modelsvector3f = NULL;
10711                         rsurface.modeltvector3f = NULL;
10712                         rsurface.modelnormal3f = NULL;
10713                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10714                         rsurface.modelvertexmesh = NULL;
10715                         rsurface.modelvertexmeshbuffer = NULL;
10716                         rsurface.modelvertexposition = NULL;
10717                         rsurface.modelvertexpositionbuffer = NULL;
10718                 }
10719                 rsurface.modelvertex3f_vertexbuffer = 0;
10720                 rsurface.modelvertex3f_bufferoffset = 0;
10721                 rsurface.modelsvector3f_vertexbuffer = 0;
10722                 rsurface.modelsvector3f_bufferoffset = 0;
10723                 rsurface.modeltvector3f_vertexbuffer = 0;
10724                 rsurface.modeltvector3f_bufferoffset = 0;
10725                 rsurface.modelnormal3f_vertexbuffer = 0;
10726                 rsurface.modelnormal3f_bufferoffset = 0;
10727                 rsurface.modelgeneratedvertex = true;
10728         }
10729         else
10730         {
10731                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10732                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10733                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10734                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10735                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10736                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10737                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10738                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10739                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10740                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10741                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10742                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10743                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10744                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10745                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10746                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10747                 rsurface.modelgeneratedvertex = false;
10748         }
10749         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10750         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10751         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10752         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10753         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10754         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10755         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10756         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10757         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10758         rsurface.modelelement3i = model->surfmesh.data_element3i;
10759         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10760         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10761         rsurface.modelelement3s = model->surfmesh.data_element3s;
10762         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10763         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10764         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10765         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10766         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10767         rsurface.modelsurfaces = model->data_surfaces;
10768         rsurface.batchgeneratedvertex = false;
10769         rsurface.batchfirstvertex = 0;
10770         rsurface.batchnumvertices = 0;
10771         rsurface.batchfirsttriangle = 0;
10772         rsurface.batchnumtriangles = 0;
10773         rsurface.batchvertex3f  = NULL;
10774         rsurface.batchvertex3f_vertexbuffer = NULL;
10775         rsurface.batchvertex3f_bufferoffset = 0;
10776         rsurface.batchsvector3f = NULL;
10777         rsurface.batchsvector3f_vertexbuffer = NULL;
10778         rsurface.batchsvector3f_bufferoffset = 0;
10779         rsurface.batchtvector3f = NULL;
10780         rsurface.batchtvector3f_vertexbuffer = NULL;
10781         rsurface.batchtvector3f_bufferoffset = 0;
10782         rsurface.batchnormal3f  = NULL;
10783         rsurface.batchnormal3f_vertexbuffer = NULL;
10784         rsurface.batchnormal3f_bufferoffset = 0;
10785         rsurface.batchlightmapcolor4f = NULL;
10786         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10787         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10788         rsurface.batchtexcoordtexture2f = NULL;
10789         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10790         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10791         rsurface.batchtexcoordlightmap2f = NULL;
10792         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10793         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10794         rsurface.batchvertexmesh = NULL;
10795         rsurface.batchvertexmeshbuffer = NULL;
10796         rsurface.batchvertexposition = NULL;
10797         rsurface.batchvertexpositionbuffer = NULL;
10798         rsurface.batchelement3i = NULL;
10799         rsurface.batchelement3i_indexbuffer = NULL;
10800         rsurface.batchelement3i_bufferoffset = 0;
10801         rsurface.batchelement3s = NULL;
10802         rsurface.batchelement3s_indexbuffer = NULL;
10803         rsurface.batchelement3s_bufferoffset = 0;
10804         rsurface.passcolor4f = NULL;
10805         rsurface.passcolor4f_vertexbuffer = NULL;
10806         rsurface.passcolor4f_bufferoffset = 0;
10807 }
10808
10809 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)
10810 {
10811         int i;
10812
10813         rsurface.entity = r_refdef.scene.worldentity;
10814         rsurface.skeleton = NULL;
10815         rsurface.ent_skinnum = 0;
10816         rsurface.ent_qwskin = -1;
10817         rsurface.ent_shadertime = shadertime;
10818         rsurface.ent_flags = entflags;
10819         rsurface.modelnumvertices = numvertices;
10820         rsurface.modelnumtriangles = numtriangles;
10821         if (rsurface.array_size < rsurface.modelnumvertices)
10822                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10823         rsurface.matrix = *matrix;
10824         rsurface.inversematrix = *inversematrix;
10825         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10826         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10827         R_EntityMatrix(&rsurface.matrix);
10828         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10829         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10830         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10831         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10832         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10833         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10834         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10835         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10836         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10837         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10838         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10839         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10840         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);
10841         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10842         rsurface.frameblend[0].lerp = 1;
10843         rsurface.ent_alttextures = false;
10844         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10845         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10846         if (wanttangents)
10847         {
10848                 rsurface.modelvertex3f = vertex3f;
10849                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10850                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10851                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10852         }
10853         else if (wantnormals)
10854         {
10855                 rsurface.modelvertex3f = vertex3f;
10856                 rsurface.modelsvector3f = NULL;
10857                 rsurface.modeltvector3f = NULL;
10858                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10859         }
10860         else
10861         {
10862                 rsurface.modelvertex3f = vertex3f;
10863                 rsurface.modelsvector3f = NULL;
10864                 rsurface.modeltvector3f = NULL;
10865                 rsurface.modelnormal3f = NULL;
10866         }
10867         rsurface.modelvertexmesh = NULL;
10868         rsurface.modelvertexmeshbuffer = NULL;
10869         rsurface.modelvertexposition = NULL;
10870         rsurface.modelvertexpositionbuffer = NULL;
10871         rsurface.modelvertex3f_vertexbuffer = 0;
10872         rsurface.modelvertex3f_bufferoffset = 0;
10873         rsurface.modelsvector3f_vertexbuffer = 0;
10874         rsurface.modelsvector3f_bufferoffset = 0;
10875         rsurface.modeltvector3f_vertexbuffer = 0;
10876         rsurface.modeltvector3f_bufferoffset = 0;
10877         rsurface.modelnormal3f_vertexbuffer = 0;
10878         rsurface.modelnormal3f_bufferoffset = 0;
10879         rsurface.modelgeneratedvertex = true;
10880         rsurface.modellightmapcolor4f  = color4f;
10881         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10882         rsurface.modellightmapcolor4f_bufferoffset = 0;
10883         rsurface.modeltexcoordtexture2f  = texcoord2f;
10884         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10885         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10886         rsurface.modeltexcoordlightmap2f  = NULL;
10887         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10888         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10889         rsurface.modelelement3i = element3i;
10890         rsurface.modelelement3i_indexbuffer = NULL;
10891         rsurface.modelelement3i_bufferoffset = 0;
10892         rsurface.modelelement3s = element3s;
10893         rsurface.modelelement3s_indexbuffer = NULL;
10894         rsurface.modelelement3s_bufferoffset = 0;
10895         rsurface.modellightmapoffsets = NULL;
10896         rsurface.modelsurfaces = NULL;
10897         rsurface.batchgeneratedvertex = false;
10898         rsurface.batchfirstvertex = 0;
10899         rsurface.batchnumvertices = 0;
10900         rsurface.batchfirsttriangle = 0;
10901         rsurface.batchnumtriangles = 0;
10902         rsurface.batchvertex3f  = NULL;
10903         rsurface.batchvertex3f_vertexbuffer = NULL;
10904         rsurface.batchvertex3f_bufferoffset = 0;
10905         rsurface.batchsvector3f = NULL;
10906         rsurface.batchsvector3f_vertexbuffer = NULL;
10907         rsurface.batchsvector3f_bufferoffset = 0;
10908         rsurface.batchtvector3f = NULL;
10909         rsurface.batchtvector3f_vertexbuffer = NULL;
10910         rsurface.batchtvector3f_bufferoffset = 0;
10911         rsurface.batchnormal3f  = NULL;
10912         rsurface.batchnormal3f_vertexbuffer = NULL;
10913         rsurface.batchnormal3f_bufferoffset = 0;
10914         rsurface.batchlightmapcolor4f = NULL;
10915         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10916         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10917         rsurface.batchtexcoordtexture2f = NULL;
10918         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10919         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10920         rsurface.batchtexcoordlightmap2f = NULL;
10921         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10922         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10923         rsurface.batchvertexmesh = NULL;
10924         rsurface.batchvertexmeshbuffer = NULL;
10925         rsurface.batchvertexposition = NULL;
10926         rsurface.batchvertexpositionbuffer = NULL;
10927         rsurface.batchelement3i = NULL;
10928         rsurface.batchelement3i_indexbuffer = NULL;
10929         rsurface.batchelement3i_bufferoffset = 0;
10930         rsurface.batchelement3s = NULL;
10931         rsurface.batchelement3s_indexbuffer = NULL;
10932         rsurface.batchelement3s_bufferoffset = 0;
10933         rsurface.passcolor4f = NULL;
10934         rsurface.passcolor4f_vertexbuffer = NULL;
10935         rsurface.passcolor4f_bufferoffset = 0;
10936
10937         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10938         {
10939                 if ((wantnormals || wanttangents) && !normal3f)
10940                 {
10941                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10942                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10943                 }
10944                 if (wanttangents && !svector3f)
10945                 {
10946                         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);
10947                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10948                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10949                 }
10950         }
10951
10952         // now convert arrays into vertexmesh structs
10953         for (i = 0;i < numvertices;i++)
10954         {
10955                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10956                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10957                 if (rsurface.modelsvector3f)
10958                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10959                 if (rsurface.modeltvector3f)
10960                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10961                 if (rsurface.modelnormal3f)
10962                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10963                 if (rsurface.modellightmapcolor4f)
10964                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10965                 if (rsurface.modeltexcoordtexture2f)
10966                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10967                 if (rsurface.modeltexcoordlightmap2f)
10968                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10969         }
10970 }
10971
10972 float RSurf_FogPoint(const float *v)
10973 {
10974         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10975         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10976         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10977         float FogHeightFade = r_refdef.fogheightfade;
10978         float fogfrac;
10979         unsigned int fogmasktableindex;
10980         if (r_refdef.fogplaneviewabove)
10981                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10982         else
10983                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10984         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10985         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10986 }
10987
10988 float RSurf_FogVertex(const float *v)
10989 {
10990         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10991         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10992         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10993         float FogHeightFade = rsurface.fogheightfade;
10994         float fogfrac;
10995         unsigned int fogmasktableindex;
10996         if (r_refdef.fogplaneviewabove)
10997                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10998         else
10999                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11000         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11001         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11002 }
11003
11004 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11005 {
11006         int i;
11007         for (i = 0;i < numelements;i++)
11008                 outelement3i[i] = inelement3i[i] + adjust;
11009 }
11010
11011 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11012 extern cvar_t gl_vbo;
11013 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11014 {
11015         int deformindex;
11016         int firsttriangle;
11017         int numtriangles;
11018         int firstvertex;
11019         int endvertex;
11020         int numvertices;
11021         int surfacefirsttriangle;
11022         int surfacenumtriangles;
11023         int surfacefirstvertex;
11024         int surfaceendvertex;
11025         int surfacenumvertices;
11026         int surfaceadjustvertex;
11027         int needsupdate;
11028         int i, j;
11029         qboolean gaps;
11030         qboolean dynamicvertex;
11031         float amplitude;
11032         float animpos;
11033         float scale;
11034         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11035         float waveparms[4];
11036         q3shaderinfo_deform_t *deform;
11037         const msurface_t *surface, *firstsurface;
11038         r_vertexposition_t *vertexposition;
11039         r_vertexmesh_t *vertexmesh;
11040         if (!texturenumsurfaces)
11041                 return;
11042         // find vertex range of this surface batch
11043         gaps = false;
11044         firstsurface = texturesurfacelist[0];
11045         firsttriangle = firstsurface->num_firsttriangle;
11046         numtriangles = 0;
11047         firstvertex = endvertex = firstsurface->num_firstvertex;
11048         for (i = 0;i < texturenumsurfaces;i++)
11049         {
11050                 surface = texturesurfacelist[i];
11051                 if (surface != firstsurface + i)
11052                         gaps = true;
11053                 surfacefirstvertex = surface->num_firstvertex;
11054                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11055                 surfacenumtriangles = surface->num_triangles;
11056                 if (firstvertex > surfacefirstvertex)
11057                         firstvertex = surfacefirstvertex;
11058                 if (endvertex < surfaceendvertex)
11059                         endvertex = surfaceendvertex;
11060                 numtriangles += surfacenumtriangles;
11061         }
11062         if (!numtriangles)
11063                 return;
11064
11065         // we now know the vertex range used, and if there are any gaps in it
11066         rsurface.batchfirstvertex = firstvertex;
11067         rsurface.batchnumvertices = endvertex - firstvertex;
11068         rsurface.batchfirsttriangle = firsttriangle;
11069         rsurface.batchnumtriangles = numtriangles;
11070
11071         // this variable holds flags for which properties have been updated that
11072         // may require regenerating vertexmesh or vertexposition arrays...
11073         needsupdate = 0;
11074
11075         // check if any dynamic vertex processing must occur
11076         dynamicvertex = false;
11077
11078         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11079                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11080         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11081         {
11082                 switch (deform->deform)
11083                 {
11084                 default:
11085                 case Q3DEFORM_PROJECTIONSHADOW:
11086                 case Q3DEFORM_TEXT0:
11087                 case Q3DEFORM_TEXT1:
11088                 case Q3DEFORM_TEXT2:
11089                 case Q3DEFORM_TEXT3:
11090                 case Q3DEFORM_TEXT4:
11091                 case Q3DEFORM_TEXT5:
11092                 case Q3DEFORM_TEXT6:
11093                 case Q3DEFORM_TEXT7:
11094                 case Q3DEFORM_NONE:
11095                         break;
11096                 case Q3DEFORM_AUTOSPRITE:
11097                         dynamicvertex = true;
11098                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11099                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11100                         break;
11101                 case Q3DEFORM_AUTOSPRITE2:
11102                         dynamicvertex = true;
11103                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11104                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11105                         break;
11106                 case Q3DEFORM_NORMAL:
11107                         dynamicvertex = true;
11108                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11109                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11110                         break;
11111                 case Q3DEFORM_WAVE:
11112                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11113                                 break; // if wavefunc is a nop, ignore this transform
11114                         dynamicvertex = true;
11115                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11116                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11117                         break;
11118                 case Q3DEFORM_BULGE:
11119                         dynamicvertex = true;
11120                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11121                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11122                         break;
11123                 case Q3DEFORM_MOVE:
11124                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11125                                 break; // if wavefunc is a nop, ignore this transform
11126                         dynamicvertex = true;
11127                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11128                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11129                         break;
11130                 }
11131         }
11132         switch(rsurface.texture->tcgen.tcgen)
11133         {
11134         default:
11135         case Q3TCGEN_TEXTURE:
11136                 break;
11137         case Q3TCGEN_LIGHTMAP:
11138                 dynamicvertex = true;
11139                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11140                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11141                 break;
11142         case Q3TCGEN_VECTOR:
11143                 dynamicvertex = true;
11144                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11145                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11146                 break;
11147         case Q3TCGEN_ENVIRONMENT:
11148                 dynamicvertex = true;
11149                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11150                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11151                 break;
11152         }
11153         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11154         {
11155                 dynamicvertex = true;
11156                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11157                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11158         }
11159
11160         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11161         {
11162                 dynamicvertex = true;
11163                 batchneed |= BATCHNEED_NOGAPS;
11164                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11165         }
11166
11167         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11168         {
11169                 dynamicvertex = true;
11170                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11171                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11172         }
11173
11174         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11175         {
11176                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11177                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11178                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11179                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11180                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11181                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11182                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11183         }
11184
11185         // when the model data has no vertex buffer (dynamic mesh), we need to
11186         // eliminate gaps
11187         if (!rsurface.modelvertexmeshbuffer)
11188                 batchneed |= BATCHNEED_NOGAPS;
11189
11190         // if needsupdate, we have to do a dynamic vertex batch for sure
11191         if (needsupdate & batchneed)
11192                 dynamicvertex = true;
11193
11194         // see if we need to build vertexmesh from arrays
11195         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11196                 dynamicvertex = true;
11197
11198         // see if we need to build vertexposition from arrays
11199         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11200                 dynamicvertex = true;
11201
11202         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11203         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11204                 dynamicvertex = true;
11205
11206         // if there is a chance of animated vertex colors, it's a dynamic batch
11207         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11208                 dynamicvertex = true;
11209
11210         rsurface.batchvertex3f = rsurface.modelvertex3f;
11211         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11212         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11213         rsurface.batchsvector3f = rsurface.modelsvector3f;
11214         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11215         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11216         rsurface.batchtvector3f = rsurface.modeltvector3f;
11217         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11218         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11219         rsurface.batchnormal3f = rsurface.modelnormal3f;
11220         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11221         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11222         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11223         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11224         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11225         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11226         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11227         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11228         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11229         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11230         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11231         rsurface.batchvertexposition = rsurface.modelvertexposition;
11232         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11233         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11234         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11235         rsurface.batchelement3i = rsurface.modelelement3i;
11236         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11237         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11238         rsurface.batchelement3s = rsurface.modelelement3s;
11239         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11240         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11241
11242         // if any dynamic vertex processing has to occur in software, we copy the
11243         // entire surface list together before processing to rebase the vertices
11244         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11245         //
11246         // if any gaps exist and we do not have a static vertex buffer, we have to
11247         // copy the surface list together to avoid wasting upload bandwidth on the
11248         // vertices in the gaps.
11249         //
11250         // if gaps exist and we have a static vertex buffer, we still have to
11251         // combine the index buffer ranges into one dynamic index buffer.
11252         //
11253         // in all cases we end up with data that can be drawn in one call.
11254
11255         if (!dynamicvertex)
11256         {
11257                 // static vertex data, just set pointers...
11258                 rsurface.batchgeneratedvertex = false;
11259                 // if there are gaps, we want to build a combined index buffer,
11260                 // otherwise use the original static buffer with an appropriate offset
11261                 if (gaps)
11262                 {
11263                         firsttriangle = 0;
11264                         numtriangles = 0;
11265                         for (i = 0;i < texturenumsurfaces;i++)
11266                         {
11267                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11268                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11269                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11270                                 numtriangles += surfacenumtriangles;
11271                         }
11272                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11273                         rsurface.batchelement3i_indexbuffer = NULL;
11274                         rsurface.batchelement3i_bufferoffset = 0;
11275                         rsurface.batchelement3s = NULL;
11276                         rsurface.batchelement3s_indexbuffer = NULL;
11277                         rsurface.batchelement3s_bufferoffset = 0;
11278                         if (endvertex <= 65536)
11279                         {
11280                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11281                                 for (i = 0;i < numtriangles*3;i++)
11282                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11283                         }
11284                         rsurface.batchfirsttriangle = firsttriangle;
11285                         rsurface.batchnumtriangles = numtriangles;
11286                 }
11287                 return;
11288         }
11289
11290         // something needs software processing, do it for real...
11291         // we only directly handle interleaved array data in this case...
11292         rsurface.batchgeneratedvertex = true;
11293
11294         // now copy the vertex data into a combined array and make an index array
11295         // (this is what Quake3 does all the time)
11296         //if (gaps || rsurface.batchfirstvertex)
11297         {
11298                 rsurface.batchvertexposition = NULL;
11299                 rsurface.batchvertexpositionbuffer = NULL;
11300                 rsurface.batchvertexmesh = NULL;
11301                 rsurface.batchvertexmeshbuffer = NULL;
11302                 rsurface.batchvertex3f = NULL;
11303                 rsurface.batchvertex3f_vertexbuffer = NULL;
11304                 rsurface.batchvertex3f_bufferoffset = 0;
11305                 rsurface.batchsvector3f = NULL;
11306                 rsurface.batchsvector3f_vertexbuffer = NULL;
11307                 rsurface.batchsvector3f_bufferoffset = 0;
11308                 rsurface.batchtvector3f = NULL;
11309                 rsurface.batchtvector3f_vertexbuffer = NULL;
11310                 rsurface.batchtvector3f_bufferoffset = 0;
11311                 rsurface.batchnormal3f = NULL;
11312                 rsurface.batchnormal3f_vertexbuffer = NULL;
11313                 rsurface.batchnormal3f_bufferoffset = 0;
11314                 rsurface.batchlightmapcolor4f = NULL;
11315                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11316                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11317                 rsurface.batchtexcoordtexture2f = NULL;
11318                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11319                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11320                 rsurface.batchtexcoordlightmap2f = NULL;
11321                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11322                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11323                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11324                 rsurface.batchelement3i_indexbuffer = NULL;
11325                 rsurface.batchelement3i_bufferoffset = 0;
11326                 rsurface.batchelement3s = NULL;
11327                 rsurface.batchelement3s_indexbuffer = NULL;
11328                 rsurface.batchelement3s_bufferoffset = 0;
11329                 // we'll only be setting up certain arrays as needed
11330                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11331                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11332                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11333                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11334                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11335                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11336                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11337                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11338                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11339                 {
11340                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11341                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11342                 }
11343                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11344                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11345                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11346                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11347                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11348                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11349                 numvertices = 0;
11350                 numtriangles = 0;
11351                 for (i = 0;i < texturenumsurfaces;i++)
11352                 {
11353                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11354                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11355                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11356                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11357                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11358                         // copy only the data requested
11359                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11360                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11361                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11362                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11363                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11364                         {
11365                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11366                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11367                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11368                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11369                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11370                                 {
11371                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11372                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11373                                 }
11374                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11375                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11376                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11377                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11378                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11379                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11380                         }
11381                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11382                         numvertices += surfacenumvertices;
11383                         numtriangles += surfacenumtriangles;
11384                 }
11385
11386                 // generate a 16bit index array as well if possible
11387                 // (in general, dynamic batches fit)
11388                 if (numvertices <= 65536)
11389                 {
11390                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11391                         for (i = 0;i < numtriangles*3;i++)
11392                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11393                 }
11394
11395                 // since we've copied everything, the batch now starts at 0
11396                 rsurface.batchfirstvertex = 0;
11397                 rsurface.batchnumvertices = numvertices;
11398                 rsurface.batchfirsttriangle = 0;
11399                 rsurface.batchnumtriangles = numtriangles;
11400         }
11401
11402         // q1bsp surfaces rendered in vertex color mode have to have colors
11403         // calculated based on lightstyles
11404         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11405         {
11406                 // generate color arrays for the surfaces in this list
11407                 int c[4];
11408                 int scale;
11409                 int size3;
11410                 const int *offsets;
11411                 const unsigned char *lm;
11412                 numvertices = 0;
11413                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11414                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11415                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11416                 for (i = 0;i < texturenumsurfaces;i++)
11417                 {
11418                         surface = texturesurfacelist[i];
11419                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11420                         surfacenumvertices = surface->num_vertices;
11421                         if (surface->lightmapinfo->samples)
11422                         {
11423                                 for (j = 0;j < surfacenumvertices;j++)
11424                                 {
11425                                         lm = surface->lightmapinfo->samples + offsets[j];
11426                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11427                                         VectorScale(lm, scale, c);
11428                                         if (surface->lightmapinfo->styles[1] != 255)
11429                                         {
11430                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11431                                                 lm += size3;
11432                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11433                                                 VectorMA(c, scale, lm, c);
11434                                                 if (surface->lightmapinfo->styles[2] != 255)
11435                                                 {
11436                                                         lm += size3;
11437                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11438                                                         VectorMA(c, scale, lm, c);
11439                                                         if (surface->lightmapinfo->styles[3] != 255)
11440                                                         {
11441                                                                 lm += size3;
11442                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11443                                                                 VectorMA(c, scale, lm, c);
11444                                                         }
11445                                                 }
11446                                         }
11447                                         c[0] >>= 15;
11448                                         c[1] >>= 15;
11449                                         c[2] >>= 15;
11450                                         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);
11451                                         numvertices++;
11452                                 }
11453                         }
11454                         else
11455                         {
11456                                 for (j = 0;j < surfacenumvertices;j++)
11457                                 {
11458                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11459                                         numvertices++;
11460                                 }
11461                         }
11462                 }
11463         }
11464
11465         // if vertices are deformed (sprite flares and things in maps, possibly
11466         // water waves, bulges and other deformations), modify the copied vertices
11467         // in place
11468         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11469         {
11470                 switch (deform->deform)
11471                 {
11472                 default:
11473                 case Q3DEFORM_PROJECTIONSHADOW:
11474                 case Q3DEFORM_TEXT0:
11475                 case Q3DEFORM_TEXT1:
11476                 case Q3DEFORM_TEXT2:
11477                 case Q3DEFORM_TEXT3:
11478                 case Q3DEFORM_TEXT4:
11479                 case Q3DEFORM_TEXT5:
11480                 case Q3DEFORM_TEXT6:
11481                 case Q3DEFORM_TEXT7:
11482                 case Q3DEFORM_NONE:
11483                         break;
11484                 case Q3DEFORM_AUTOSPRITE:
11485                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11486                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11487                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11488                         VectorNormalize(newforward);
11489                         VectorNormalize(newright);
11490                         VectorNormalize(newup);
11491                         // a single autosprite surface can contain multiple sprites...
11492                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11493                         {
11494                                 VectorClear(center);
11495                                 for (i = 0;i < 4;i++)
11496                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11497                                 VectorScale(center, 0.25f, center);
11498                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11499                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11500                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11501                                 for (i = 0;i < 4;i++)
11502                                 {
11503                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11504                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11505                                 }
11506                         }
11507                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11508                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11509                         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);
11510                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11511                         rsurface.batchvertex3f_vertexbuffer = NULL;
11512                         rsurface.batchvertex3f_bufferoffset = 0;
11513                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11514                         rsurface.batchsvector3f_vertexbuffer = NULL;
11515                         rsurface.batchsvector3f_bufferoffset = 0;
11516                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11517                         rsurface.batchtvector3f_vertexbuffer = NULL;
11518                         rsurface.batchtvector3f_bufferoffset = 0;
11519                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11520                         rsurface.batchnormal3f_vertexbuffer = NULL;
11521                         rsurface.batchnormal3f_bufferoffset = 0;
11522                         break;
11523                 case Q3DEFORM_AUTOSPRITE2:
11524                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11525                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11526                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11527                         VectorNormalize(newforward);
11528                         VectorNormalize(newright);
11529                         VectorNormalize(newup);
11530                         {
11531                                 const float *v1, *v2;
11532                                 vec3_t start, end;
11533                                 float f, l;
11534                                 struct
11535                                 {
11536                                         float length2;
11537                                         const float *v1;
11538                                         const float *v2;
11539                                 }
11540                                 shortest[2];
11541                                 memset(shortest, 0, sizeof(shortest));
11542                                 // a single autosprite surface can contain multiple sprites...
11543                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11544                                 {
11545                                         VectorClear(center);
11546                                         for (i = 0;i < 4;i++)
11547                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11548                                         VectorScale(center, 0.25f, center);
11549                                         // find the two shortest edges, then use them to define the
11550                                         // axis vectors for rotating around the central axis
11551                                         for (i = 0;i < 6;i++)
11552                                         {
11553                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11554                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11555                                                 l = VectorDistance2(v1, v2);
11556                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11557                                                 if (v1[2] != v2[2])
11558                                                         l += (1.0f / 1024.0f);
11559                                                 if (shortest[0].length2 > l || i == 0)
11560                                                 {
11561                                                         shortest[1] = shortest[0];
11562                                                         shortest[0].length2 = l;
11563                                                         shortest[0].v1 = v1;
11564                                                         shortest[0].v2 = v2;
11565                                                 }
11566                                                 else if (shortest[1].length2 > l || i == 1)
11567                                                 {
11568                                                         shortest[1].length2 = l;
11569                                                         shortest[1].v1 = v1;
11570                                                         shortest[1].v2 = v2;
11571                                                 }
11572                                         }
11573                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11574                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11575                                         // this calculates the right vector from the shortest edge
11576                                         // and the up vector from the edge midpoints
11577                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11578                                         VectorNormalize(right);
11579                                         VectorSubtract(end, start, up);
11580                                         VectorNormalize(up);
11581                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11582                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11583                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11584                                         VectorNegate(forward, forward);
11585                                         VectorReflect(forward, 0, up, forward);
11586                                         VectorNormalize(forward);
11587                                         CrossProduct(up, forward, newright);
11588                                         VectorNormalize(newright);
11589                                         // rotate the quad around the up axis vector, this is made
11590                                         // especially easy by the fact we know the quad is flat,
11591                                         // so we only have to subtract the center position and
11592                                         // measure distance along the right vector, and then
11593                                         // multiply that by the newright vector and add back the
11594                                         // center position
11595                                         // we also need to subtract the old position to undo the
11596                                         // displacement from the center, which we do with a
11597                                         // DotProduct, the subtraction/addition of center is also
11598                                         // optimized into DotProducts here
11599                                         l = DotProduct(right, center);
11600                                         for (i = 0;i < 4;i++)
11601                                         {
11602                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11603                                                 f = DotProduct(right, v1) - l;
11604                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11605                                         }
11606                                 }
11607                         }
11608                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11609                         rsurface.batchvertex3f_vertexbuffer = NULL;
11610                         rsurface.batchvertex3f_bufferoffset = 0;
11611                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11612                         {
11613                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11614                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11615                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11616                                 rsurface.batchnormal3f_bufferoffset = 0;
11617                         }
11618                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11619                         {
11620                                 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);
11621                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11622                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11623                                 rsurface.batchsvector3f_bufferoffset = 0;
11624                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11625                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11626                                 rsurface.batchtvector3f_bufferoffset = 0;
11627                         }
11628                         break;
11629                 case Q3DEFORM_NORMAL:
11630                         // deform the normals to make reflections wavey
11631                         for (j = 0;j < rsurface.batchnumvertices;j++)
11632                         {
11633                                 float vertex[3];
11634                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11635                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11636                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11637                                 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]);
11638                                 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]);
11639                                 VectorNormalize(normal);
11640                         }
11641                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11642                         rsurface.batchnormal3f_vertexbuffer = NULL;
11643                         rsurface.batchnormal3f_bufferoffset = 0;
11644                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11645                         {
11646                                 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);
11647                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11648                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11649                                 rsurface.batchsvector3f_bufferoffset = 0;
11650                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11651                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11652                                 rsurface.batchtvector3f_bufferoffset = 0;
11653                         }
11654                         break;
11655                 case Q3DEFORM_WAVE:
11656                         // deform vertex array to make wavey water and flags and such
11657                         waveparms[0] = deform->waveparms[0];
11658                         waveparms[1] = deform->waveparms[1];
11659                         waveparms[2] = deform->waveparms[2];
11660                         waveparms[3] = deform->waveparms[3];
11661                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11662                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11663                         // this is how a divisor of vertex influence on deformation
11664                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11665                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11666                         for (j = 0;j < rsurface.batchnumvertices;j++)
11667                         {
11668                                 // if the wavefunc depends on time, evaluate it per-vertex
11669                                 if (waveparms[3])
11670                                 {
11671                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11672                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11673                                 }
11674                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11675                         }
11676                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11677                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11678                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11679                         rsurface.batchvertex3f_vertexbuffer = NULL;
11680                         rsurface.batchvertex3f_bufferoffset = 0;
11681                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11682                         rsurface.batchnormal3f_vertexbuffer = NULL;
11683                         rsurface.batchnormal3f_bufferoffset = 0;
11684                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11685                         {
11686                                 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);
11687                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11688                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11689                                 rsurface.batchsvector3f_bufferoffset = 0;
11690                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11691                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11692                                 rsurface.batchtvector3f_bufferoffset = 0;
11693                         }
11694                         break;
11695                 case Q3DEFORM_BULGE:
11696                         // deform vertex array to make the surface have moving bulges
11697                         for (j = 0;j < rsurface.batchnumvertices;j++)
11698                         {
11699                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11700                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11701                         }
11702                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11703                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11704                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11705                         rsurface.batchvertex3f_vertexbuffer = NULL;
11706                         rsurface.batchvertex3f_bufferoffset = 0;
11707                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11708                         rsurface.batchnormal3f_vertexbuffer = NULL;
11709                         rsurface.batchnormal3f_bufferoffset = 0;
11710                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11711                         {
11712                                 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);
11713                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11714                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11715                                 rsurface.batchsvector3f_bufferoffset = 0;
11716                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11717                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11718                                 rsurface.batchtvector3f_bufferoffset = 0;
11719                         }
11720                         break;
11721                 case Q3DEFORM_MOVE:
11722                         // deform vertex array
11723                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11724                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11725                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11726                         VectorScale(deform->parms, scale, waveparms);
11727                         for (j = 0;j < rsurface.batchnumvertices;j++)
11728                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11729                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11730                         rsurface.batchvertex3f_vertexbuffer = NULL;
11731                         rsurface.batchvertex3f_bufferoffset = 0;
11732                         break;
11733                 }
11734         }
11735
11736         // generate texcoords based on the chosen texcoord source
11737         switch(rsurface.texture->tcgen.tcgen)
11738         {
11739         default:
11740         case Q3TCGEN_TEXTURE:
11741                 break;
11742         case Q3TCGEN_LIGHTMAP:
11743                 if (rsurface.batchtexcoordlightmap2f)
11744                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11745                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11746                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11747                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11748                 break;
11749         case Q3TCGEN_VECTOR:
11750                 for (j = 0;j < rsurface.batchnumvertices;j++)
11751                 {
11752                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11753                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11754                 }
11755                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11756                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11757                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11758                 break;
11759         case Q3TCGEN_ENVIRONMENT:
11760                 // make environment reflections using a spheremap
11761                 for (j = 0;j < rsurface.batchnumvertices;j++)
11762                 {
11763                         // identical to Q3A's method, but executed in worldspace so
11764                         // carried models can be shiny too
11765
11766                         float viewer[3], d, reflected[3], worldreflected[3];
11767
11768                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11769                         // VectorNormalize(viewer);
11770
11771                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11772
11773                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11774                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11775                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11776                         // note: this is proportinal to viewer, so we can normalize later
11777
11778                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11779                         VectorNormalize(worldreflected);
11780
11781                         // note: this sphere map only uses world x and z!
11782                         // so positive and negative y will LOOK THE SAME.
11783                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11784                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11785                 }
11786                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11787                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11788                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11789                 break;
11790         }
11791         // the only tcmod that needs software vertex processing is turbulent, so
11792         // check for it here and apply the changes if needed
11793         // and we only support that as the first one
11794         // (handling a mixture of turbulent and other tcmods would be problematic
11795         //  without punting it entirely to a software path)
11796         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11797         {
11798                 amplitude = rsurface.texture->tcmods[0].parms[1];
11799                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11800                 for (j = 0;j < rsurface.batchnumvertices;j++)
11801                 {
11802                         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);
11803                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11804                 }
11805                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11806                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11807                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11808         }
11809
11810         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11811         {
11812                 // convert the modified arrays to vertex structs
11813                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11814                 rsurface.batchvertexmeshbuffer = NULL;
11815                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11816                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11817                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11818                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11819                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11820                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11821                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11822                 {
11823                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11824                         {
11825                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11826                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11827                         }
11828                 }
11829                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11830                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11831                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11832                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11833                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11834                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11835                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11836                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11837                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11838         }
11839
11840         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11841         {
11842                 // convert the modified arrays to vertex structs
11843                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11844                 rsurface.batchvertexpositionbuffer = NULL;
11845                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11846                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11847                 else
11848                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11849                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11850         }
11851 }
11852
11853 void RSurf_DrawBatch(void)
11854 {
11855         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);
11856 }
11857
11858 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11859 {
11860         // pick the closest matching water plane
11861         int planeindex, vertexindex, bestplaneindex = -1;
11862         float d, bestd;
11863         vec3_t vert;
11864         const float *v;
11865         r_waterstate_waterplane_t *p;
11866         bestd = 0;
11867         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11868         {
11869                 if(p->camera_entity != rsurface.texture->camera_entity)
11870                         continue;
11871                 d = 0;
11872                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11873                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11874                 {
11875                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11876                         d += fabs(PlaneDiff(vert, &p->plane));
11877                 }
11878                 if (bestd > d || bestplaneindex < 0)
11879                 {
11880                         bestd = d;
11881                         bestplaneindex = planeindex;
11882                 }
11883         }
11884         return bestplaneindex;
11885 }
11886
11887 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11888 {
11889         int i;
11890         for (i = 0;i < rsurface.batchnumvertices;i++)
11891                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11892         rsurface.passcolor4f = rsurface.array_passcolor4f;
11893         rsurface.passcolor4f_vertexbuffer = 0;
11894         rsurface.passcolor4f_bufferoffset = 0;
11895 }
11896
11897 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11898 {
11899         int i;
11900         float f;
11901         const float *v;
11902         const float *c;
11903         float *c2;
11904         if (rsurface.passcolor4f)
11905         {
11906                 // generate color arrays
11907                 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)
11908                 {
11909                         f = RSurf_FogVertex(v);
11910                         c2[0] = c[0] * f;
11911                         c2[1] = c[1] * f;
11912                         c2[2] = c[2] * f;
11913                         c2[3] = c[3];
11914                 }
11915         }
11916         else
11917         {
11918                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11919                 {
11920                         f = RSurf_FogVertex(v);
11921                         c2[0] = f;
11922                         c2[1] = f;
11923                         c2[2] = f;
11924                         c2[3] = 1;
11925                 }
11926         }
11927         rsurface.passcolor4f = rsurface.array_passcolor4f;
11928         rsurface.passcolor4f_vertexbuffer = 0;
11929         rsurface.passcolor4f_bufferoffset = 0;
11930 }
11931
11932 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11933 {
11934         int i;
11935         float f;
11936         const float *v;
11937         const float *c;
11938         float *c2;
11939         if (!rsurface.passcolor4f)
11940                 return;
11941         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
11942         {
11943                 f = RSurf_FogVertex(v);
11944                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11945                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11946                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11947                 c2[3] = c[3];
11948         }
11949         rsurface.passcolor4f = rsurface.array_passcolor4f;
11950         rsurface.passcolor4f_vertexbuffer = 0;
11951         rsurface.passcolor4f_bufferoffset = 0;
11952 }
11953
11954 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11955 {
11956         int i;
11957         const float *c;
11958         float *c2;
11959         if (!rsurface.passcolor4f)
11960                 return;
11961         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11962         {
11963                 c2[0] = c[0] * r;
11964                 c2[1] = c[1] * g;
11965                 c2[2] = c[2] * b;
11966                 c2[3] = c[3] * a;
11967         }
11968         rsurface.passcolor4f = rsurface.array_passcolor4f;
11969         rsurface.passcolor4f_vertexbuffer = 0;
11970         rsurface.passcolor4f_bufferoffset = 0;
11971 }
11972
11973 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11974 {
11975         int i;
11976         const float *c;
11977         float *c2;
11978         if (!rsurface.passcolor4f)
11979                 return;
11980         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11981         {
11982                 c2[0] = c[0] + r_refdef.scene.ambient;
11983                 c2[1] = c[1] + r_refdef.scene.ambient;
11984                 c2[2] = c[2] + r_refdef.scene.ambient;
11985                 c2[3] = c[3];
11986         }
11987         rsurface.passcolor4f = rsurface.array_passcolor4f;
11988         rsurface.passcolor4f_vertexbuffer = 0;
11989         rsurface.passcolor4f_bufferoffset = 0;
11990 }
11991
11992 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11993 {
11994         // TODO: optimize
11995         rsurface.passcolor4f = NULL;
11996         rsurface.passcolor4f_vertexbuffer = 0;
11997         rsurface.passcolor4f_bufferoffset = 0;
11998         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11999         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12000         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12001         GL_Color(r, g, b, a);
12002         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12003         RSurf_DrawBatch();
12004 }
12005
12006 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12007 {
12008         // TODO: optimize applyfog && applycolor case
12009         // just apply fog if necessary, and tint the fog color array if necessary
12010         rsurface.passcolor4f = NULL;
12011         rsurface.passcolor4f_vertexbuffer = 0;
12012         rsurface.passcolor4f_bufferoffset = 0;
12013         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12014         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12015         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12016         GL_Color(r, g, b, a);
12017         RSurf_DrawBatch();
12018 }
12019
12020 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12021 {
12022         // TODO: optimize
12023         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12024         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12025         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12026         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12027         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12028         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12029         GL_Color(r, g, b, a);
12030         RSurf_DrawBatch();
12031 }
12032
12033 static void RSurf_DrawBatch_GL11_ClampColor(void)
12034 {
12035         int i;
12036         const float *c1;
12037         float *c2;
12038         if (!rsurface.passcolor4f)
12039                 return;
12040         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12041         {
12042                 c2[0] = bound(0.0f, c1[0], 1.0f);
12043                 c2[1] = bound(0.0f, c1[1], 1.0f);
12044                 c2[2] = bound(0.0f, c1[2], 1.0f);
12045                 c2[3] = bound(0.0f, c1[3], 1.0f);
12046         }
12047 }
12048
12049 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12050 {
12051         int i;
12052         float f;
12053         float alpha;
12054         const float *v;
12055         const float *n;
12056         float *c;
12057         vec3_t ambientcolor;
12058         vec3_t diffusecolor;
12059         vec3_t lightdir;
12060         // TODO: optimize
12061         // model lighting
12062         VectorCopy(rsurface.modellight_lightdir, lightdir);
12063         f = 0.5f * r_refdef.lightmapintensity;
12064         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12065         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12066         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12067         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12068         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12069         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12070         alpha = *a;
12071         if (VectorLength2(diffusecolor) > 0)
12072         {
12073                 // q3-style directional shading
12074                 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)
12075                 {
12076                         if ((f = DotProduct(n, lightdir)) > 0)
12077                                 VectorMA(ambientcolor, f, diffusecolor, c);
12078                         else
12079                                 VectorCopy(ambientcolor, c);
12080                         c[3] = alpha;
12081                 }
12082                 *r = 1;
12083                 *g = 1;
12084                 *b = 1;
12085                 *a = 1;
12086                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12087                 rsurface.passcolor4f_vertexbuffer = 0;
12088                 rsurface.passcolor4f_bufferoffset = 0;
12089                 *applycolor = false;
12090         }
12091         else
12092         {
12093                 *r = ambientcolor[0];
12094                 *g = ambientcolor[1];
12095                 *b = ambientcolor[2];
12096                 rsurface.passcolor4f = NULL;
12097                 rsurface.passcolor4f_vertexbuffer = 0;
12098                 rsurface.passcolor4f_bufferoffset = 0;
12099         }
12100 }
12101
12102 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12103 {
12104         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12105         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12106         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12107         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12108         GL_Color(r, g, b, a);
12109         RSurf_DrawBatch();
12110 }
12111
12112 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12113 {
12114         int i;
12115         float f;
12116         const float *v;
12117         float *c;
12118         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12119         {
12120                 f = 1 - RSurf_FogVertex(v);
12121                 c[0] = r;
12122                 c[1] = g;
12123                 c[2] = b;
12124                 c[3] = f * a;
12125         }
12126 }
12127
12128 void RSurf_SetupDepthAndCulling(void)
12129 {
12130         // submodels are biased to avoid z-fighting with world surfaces that they
12131         // may be exactly overlapping (avoids z-fighting artifacts on certain
12132         // doors and things in Quake maps)
12133         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12134         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12135         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12136         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12137 }
12138
12139 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12140 {
12141         // transparent sky would be ridiculous
12142         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12143                 return;
12144         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12145         skyrenderlater = true;
12146         RSurf_SetupDepthAndCulling();
12147         GL_DepthMask(true);
12148         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12149         // skymasking on them, and Quake3 never did sky masking (unlike
12150         // software Quake and software Quake2), so disable the sky masking
12151         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12152         // and skymasking also looks very bad when noclipping outside the
12153         // level, so don't use it then either.
12154         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12155         {
12156                 R_Mesh_ResetTextureState();
12157                 if (skyrendermasked)
12158                 {
12159                         R_SetupShader_DepthOrShadow();
12160                         // depth-only (masking)
12161                         GL_ColorMask(0,0,0,0);
12162                         // just to make sure that braindead drivers don't draw
12163                         // anything despite that colormask...
12164                         GL_BlendFunc(GL_ZERO, GL_ONE);
12165                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12166                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12167                 }
12168                 else
12169                 {
12170                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12171                         // fog sky
12172                         GL_BlendFunc(GL_ONE, GL_ZERO);
12173                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12174                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12175                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12176                 }
12177                 RSurf_DrawBatch();
12178                 if (skyrendermasked)
12179                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12180         }
12181         R_Mesh_ResetTextureState();
12182         GL_Color(1, 1, 1, 1);
12183 }
12184
12185 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12186 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12187 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12188 {
12189         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12190                 return;
12191         if (prepass)
12192         {
12193                 // render screenspace normalmap to texture
12194                 GL_DepthMask(true);
12195                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12196                 RSurf_DrawBatch();
12197                 return;
12198         }
12199
12200         // bind lightmap texture
12201
12202         // water/refraction/reflection/camera surfaces have to be handled specially
12203         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12204         {
12205                 int start, end, startplaneindex;
12206                 for (start = 0;start < texturenumsurfaces;start = end)
12207                 {
12208                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12209                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12210                                 ;
12211                         // now that we have a batch using the same planeindex, render it
12212                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12213                         {
12214                                 // render water or distortion background
12215                                 GL_DepthMask(true);
12216                                 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));
12217                                 RSurf_DrawBatch();
12218                                 // blend surface on top
12219                                 GL_DepthMask(false);
12220                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12221                                 RSurf_DrawBatch();
12222                         }
12223                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12224                         {
12225                                 // render surface with reflection texture as input
12226                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12227                                 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));
12228                                 RSurf_DrawBatch();
12229                         }
12230                 }
12231                 return;
12232         }
12233
12234         // render surface batch normally
12235         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12236         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12237         RSurf_DrawBatch();
12238 }
12239
12240 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12241 {
12242         // OpenGL 1.3 path - anything not completely ancient
12243         qboolean applycolor;
12244         qboolean applyfog;
12245         int layerindex;
12246         const texturelayer_t *layer;
12247         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);
12248         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12249
12250         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12251         {
12252                 vec4_t layercolor;
12253                 int layertexrgbscale;
12254                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12255                 {
12256                         if (layerindex == 0)
12257                                 GL_AlphaTest(true);
12258                         else
12259                         {
12260                                 GL_AlphaTest(false);
12261                                 GL_DepthFunc(GL_EQUAL);
12262                         }
12263                 }
12264                 GL_DepthMask(layer->depthmask && writedepth);
12265                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12266                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12267                 {
12268                         layertexrgbscale = 4;
12269                         VectorScale(layer->color, 0.25f, layercolor);
12270                 }
12271                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12272                 {
12273                         layertexrgbscale = 2;
12274                         VectorScale(layer->color, 0.5f, layercolor);
12275                 }
12276                 else
12277                 {
12278                         layertexrgbscale = 1;
12279                         VectorScale(layer->color, 1.0f, layercolor);
12280                 }
12281                 layercolor[3] = layer->color[3];
12282                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12283                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12284                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12285                 switch (layer->type)
12286                 {
12287                 case TEXTURELAYERTYPE_LITTEXTURE:
12288                         // single-pass lightmapped texture with 2x rgbscale
12289                         R_Mesh_TexBind(0, r_texture_white);
12290                         R_Mesh_TexMatrix(0, NULL);
12291                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12292                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12293                         R_Mesh_TexBind(1, layer->texture);
12294                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12295                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12296                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12297                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12298                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12299                         else if (rsurface.uselightmaptexture)
12300                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12301                         else
12302                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12303                         break;
12304                 case TEXTURELAYERTYPE_TEXTURE:
12305                         // singletexture unlit texture with transparency support
12306                         R_Mesh_TexBind(0, layer->texture);
12307                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12308                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12309                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12310                         R_Mesh_TexBind(1, 0);
12311                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12312                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12313                         break;
12314                 case TEXTURELAYERTYPE_FOG:
12315                         // singletexture fogging
12316                         if (layer->texture)
12317                         {
12318                                 R_Mesh_TexBind(0, layer->texture);
12319                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12320                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12321                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12322                         }
12323                         else
12324                         {
12325                                 R_Mesh_TexBind(0, 0);
12326                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12327                         }
12328                         R_Mesh_TexBind(1, 0);
12329                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12330                         // generate a color array for the fog pass
12331                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12332                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12333                         RSurf_DrawBatch();
12334                         break;
12335                 default:
12336                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12337                 }
12338         }
12339         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12340         {
12341                 GL_DepthFunc(GL_LEQUAL);
12342                 GL_AlphaTest(false);
12343         }
12344 }
12345
12346 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12347 {
12348         // OpenGL 1.1 - crusty old voodoo path
12349         qboolean applyfog;
12350         int layerindex;
12351         const texturelayer_t *layer;
12352         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);
12353         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12354
12355         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12356         {
12357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12358                 {
12359                         if (layerindex == 0)
12360                                 GL_AlphaTest(true);
12361                         else
12362                         {
12363                                 GL_AlphaTest(false);
12364                                 GL_DepthFunc(GL_EQUAL);
12365                         }
12366                 }
12367                 GL_DepthMask(layer->depthmask && writedepth);
12368                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12369                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12370                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12371                 switch (layer->type)
12372                 {
12373                 case TEXTURELAYERTYPE_LITTEXTURE:
12374                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12375                         {
12376                                 // two-pass lit texture with 2x rgbscale
12377                                 // first the lightmap pass
12378                                 R_Mesh_TexBind(0, r_texture_white);
12379                                 R_Mesh_TexMatrix(0, NULL);
12380                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12381                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12382                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12383                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12384                                 else if (rsurface.uselightmaptexture)
12385                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12386                                 else
12387                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12388                                 // then apply the texture to it
12389                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12390                                 R_Mesh_TexBind(0, layer->texture);
12391                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12392                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12393                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12394                                 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);
12395                         }
12396                         else
12397                         {
12398                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12399                                 R_Mesh_TexBind(0, layer->texture);
12400                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12401                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12402                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12403                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12404                                         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);
12405                                 else
12406                                         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);
12407                         }
12408                         break;
12409                 case TEXTURELAYERTYPE_TEXTURE:
12410                         // singletexture unlit texture with transparency support
12411                         R_Mesh_TexBind(0, layer->texture);
12412                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12413                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12414                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12415                         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);
12416                         break;
12417                 case TEXTURELAYERTYPE_FOG:
12418                         // singletexture fogging
12419                         if (layer->texture)
12420                         {
12421                                 R_Mesh_TexBind(0, layer->texture);
12422                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12423                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12424                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12425                         }
12426                         else
12427                         {
12428                                 R_Mesh_TexBind(0, 0);
12429                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12430                         }
12431                         // generate a color array for the fog pass
12432                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12433                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12434                         RSurf_DrawBatch();
12435                         break;
12436                 default:
12437                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12438                 }
12439         }
12440         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12441         {
12442                 GL_DepthFunc(GL_LEQUAL);
12443                 GL_AlphaTest(false);
12444         }
12445 }
12446
12447 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12448 {
12449         int vi;
12450         int j;
12451         r_vertexgeneric_t *batchvertex;
12452         float c[4];
12453
12454         GL_AlphaTest(false);
12455         R_Mesh_ResetTextureState();
12456         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12457
12458         if(rsurface.texture && rsurface.texture->currentskinframe)
12459         {
12460                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12461                 c[3] *= rsurface.texture->currentalpha;
12462         }
12463         else
12464         {
12465                 c[0] = 1;
12466                 c[1] = 0;
12467                 c[2] = 1;
12468                 c[3] = 1;
12469         }
12470
12471         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12472         {
12473                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12474                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12475                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12476         }
12477
12478         // brighten it up (as texture value 127 means "unlit")
12479         c[0] *= 2 * r_refdef.view.colorscale;
12480         c[1] *= 2 * r_refdef.view.colorscale;
12481         c[2] *= 2 * r_refdef.view.colorscale;
12482
12483         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12484                 c[3] *= r_wateralpha.value;
12485
12486         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12487         {
12488                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12489                 GL_DepthMask(false);
12490         }
12491         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12492         {
12493                 GL_BlendFunc(GL_ONE, GL_ONE);
12494                 GL_DepthMask(false);
12495         }
12496         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12497         {
12498                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12499                 GL_DepthMask(false);
12500         }
12501         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12502         {
12503                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12504                 GL_DepthMask(false);
12505         }
12506         else
12507         {
12508                 GL_BlendFunc(GL_ONE, GL_ZERO);
12509                 GL_DepthMask(writedepth);
12510         }
12511
12512         if (r_showsurfaces.integer == 3)
12513         {
12514                 rsurface.passcolor4f = NULL;
12515
12516                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12517                 {
12518                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12519
12520                         rsurface.passcolor4f = NULL;
12521                         rsurface.passcolor4f_vertexbuffer = 0;
12522                         rsurface.passcolor4f_bufferoffset = 0;
12523                 }
12524                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12525                 {
12526                         qboolean applycolor = true;
12527                         float one = 1.0;
12528
12529                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12530
12531                         r_refdef.lightmapintensity = 1;
12532                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12533                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12534                 }
12535                 else
12536                 {
12537                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12538
12539                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12540                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12541                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12542                 }
12543
12544                 if(!rsurface.passcolor4f)
12545                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12546
12547                 RSurf_DrawBatch_GL11_ApplyAmbient();
12548                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12549                 if(r_refdef.fogenabled)
12550                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12551                 RSurf_DrawBatch_GL11_ClampColor();
12552
12553                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12554                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12555                 RSurf_DrawBatch();
12556         }
12557         else if (!r_refdef.view.showdebug)
12558         {
12559                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12560                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12561                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12562                 {
12563                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12564                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12565                 }
12566                 R_Mesh_PrepareVertices_Generic_Unlock();
12567                 RSurf_DrawBatch();
12568         }
12569         else if (r_showsurfaces.integer == 4)
12570         {
12571                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12572                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12573                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12574                 {
12575                         unsigned char c = vi << 3;
12576                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12577                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12578                 }
12579                 R_Mesh_PrepareVertices_Generic_Unlock();
12580                 RSurf_DrawBatch();
12581         }
12582         else if (r_showsurfaces.integer == 2)
12583         {
12584                 const int *e;
12585                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12586                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12587                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12588                 {
12589                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12590                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12591                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12592                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12593                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12594                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12595                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12596                 }
12597                 R_Mesh_PrepareVertices_Generic_Unlock();
12598                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12599         }
12600         else
12601         {
12602                 int texturesurfaceindex;
12603                 int k;
12604                 const msurface_t *surface;
12605                 unsigned char surfacecolor4ub[4];
12606                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12607                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12608                 vi = 0;
12609                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12610                 {
12611                         surface = texturesurfacelist[texturesurfaceindex];
12612                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12613                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12614                         for (j = 0;j < surface->num_vertices;j++)
12615                         {
12616                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12617                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12618                                 vi++;
12619                         }
12620                 }
12621                 R_Mesh_PrepareVertices_Generic_Unlock();
12622                 RSurf_DrawBatch();
12623         }
12624 }
12625
12626 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12627 {
12628         CHECKGLERROR
12629         RSurf_SetupDepthAndCulling();
12630         if (r_showsurfaces.integer)
12631         {
12632                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12633                 return;
12634         }
12635         switch (vid.renderpath)
12636         {
12637         case RENDERPATH_GL20:
12638         case RENDERPATH_CGGL:
12639         case RENDERPATH_D3D9:
12640         case RENDERPATH_D3D10:
12641         case RENDERPATH_D3D11:
12642                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12643                 break;
12644         case RENDERPATH_GL13:
12645                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12646                 break;
12647         case RENDERPATH_GL11:
12648                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12649                 break;
12650         }
12651         CHECKGLERROR
12652 }
12653
12654 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12655 {
12656         CHECKGLERROR
12657         RSurf_SetupDepthAndCulling();
12658         if (r_showsurfaces.integer)
12659         {
12660                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12661                 return;
12662         }
12663         switch (vid.renderpath)
12664         {
12665         case RENDERPATH_GL20:
12666         case RENDERPATH_CGGL:
12667         case RENDERPATH_D3D9:
12668         case RENDERPATH_D3D10:
12669         case RENDERPATH_D3D11:
12670                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12671                 break;
12672         case RENDERPATH_GL13:
12673                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12674                 break;
12675         case RENDERPATH_GL11:
12676                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12677                 break;
12678         }
12679         CHECKGLERROR
12680 }
12681
12682 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12683 {
12684         int i, j;
12685         int texturenumsurfaces, endsurface;
12686         texture_t *texture;
12687         const msurface_t *surface;
12688 #define MAXBATCH_TRANSPARENTSURFACES 256
12689         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12690
12691         // if the model is static it doesn't matter what value we give for
12692         // wantnormals and wanttangents, so this logic uses only rules applicable
12693         // to a model, knowing that they are meaningless otherwise
12694         if (ent == r_refdef.scene.worldentity)
12695                 RSurf_ActiveWorldEntity();
12696         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12697                 RSurf_ActiveModelEntity(ent, false, false, false);
12698         else
12699         {
12700                 switch (vid.renderpath)
12701                 {
12702                 case RENDERPATH_GL20:
12703                 case RENDERPATH_CGGL:
12704                 case RENDERPATH_D3D9:
12705                 case RENDERPATH_D3D10:
12706                 case RENDERPATH_D3D11:
12707                         RSurf_ActiveModelEntity(ent, true, true, false);
12708                         break;
12709                 case RENDERPATH_GL13:
12710                 case RENDERPATH_GL11:
12711                         RSurf_ActiveModelEntity(ent, true, false, false);
12712                         break;
12713                 }
12714         }
12715
12716         if (r_transparentdepthmasking.integer)
12717         {
12718                 qboolean setup = false;
12719                 for (i = 0;i < numsurfaces;i = j)
12720                 {
12721                         j = i + 1;
12722                         surface = rsurface.modelsurfaces + surfacelist[i];
12723                         texture = surface->texture;
12724                         rsurface.texture = R_GetCurrentTexture(texture);
12725                         rsurface.lightmaptexture = NULL;
12726                         rsurface.deluxemaptexture = NULL;
12727                         rsurface.uselightmaptexture = false;
12728                         // scan ahead until we find a different texture
12729                         endsurface = min(i + 1024, numsurfaces);
12730                         texturenumsurfaces = 0;
12731                         texturesurfacelist[texturenumsurfaces++] = surface;
12732                         for (;j < endsurface;j++)
12733                         {
12734                                 surface = rsurface.modelsurfaces + surfacelist[j];
12735                                 if (texture != surface->texture)
12736                                         break;
12737                                 texturesurfacelist[texturenumsurfaces++] = surface;
12738                         }
12739                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12740                                 continue;
12741                         // render the range of surfaces as depth
12742                         if (!setup)
12743                         {
12744                                 setup = true;
12745                                 GL_ColorMask(0,0,0,0);
12746                                 GL_Color(1,1,1,1);
12747                                 GL_DepthTest(true);
12748                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12749                                 GL_DepthMask(true);
12750                                 GL_AlphaTest(false);
12751                                 R_Mesh_ResetTextureState();
12752                                 R_SetupShader_DepthOrShadow();
12753                         }
12754                         RSurf_SetupDepthAndCulling();
12755                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12756                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12757                         RSurf_DrawBatch();
12758                 }
12759                 if (setup)
12760                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12761         }
12762
12763         for (i = 0;i < numsurfaces;i = j)
12764         {
12765                 j = i + 1;
12766                 surface = rsurface.modelsurfaces + surfacelist[i];
12767                 texture = surface->texture;
12768                 rsurface.texture = R_GetCurrentTexture(texture);
12769                 rsurface.lightmaptexture = surface->lightmaptexture;
12770                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12771                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12772                 // scan ahead until we find a different texture
12773                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12774                 texturenumsurfaces = 0;
12775                 texturesurfacelist[texturenumsurfaces++] = surface;
12776                 for (;j < endsurface;j++)
12777                 {
12778                         surface = rsurface.modelsurfaces + surfacelist[j];
12779                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12780                                 break;
12781                         texturesurfacelist[texturenumsurfaces++] = surface;
12782                 }
12783                 // render the range of surfaces
12784                 if (ent == r_refdef.scene.worldentity)
12785                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12786                 else
12787                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12788         }
12789         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12790         GL_AlphaTest(false);
12791 }
12792
12793 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12794 {
12795         // transparent surfaces get pushed off into the transparent queue
12796         int surfacelistindex;
12797         const msurface_t *surface;
12798         vec3_t tempcenter, center;
12799         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12800         {
12801                 surface = texturesurfacelist[surfacelistindex];
12802                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12803                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12804                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12805                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12806                 if (queueentity->transparent_offset) // transparent offset
12807                 {
12808                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12809                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12810                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12811                 }
12812                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12813         }
12814 }
12815
12816 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12817 {
12818         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12819                 return;
12820         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12821                 return;
12822         RSurf_SetupDepthAndCulling();
12823         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12824         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12825         RSurf_DrawBatch();
12826 }
12827
12828 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12829 {
12830         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12831         CHECKGLERROR
12832         if (depthonly)
12833                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12834         else if (prepass)
12835         {
12836                 if (!rsurface.texture->currentnumlayers)
12837                         return;
12838                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12839                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12840                 else
12841                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12842         }
12843         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12844                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12845         else if (!rsurface.texture->currentnumlayers)
12846                 return;
12847         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12848         {
12849                 // in the deferred case, transparent surfaces were queued during prepass
12850                 if (!r_shadow_usingdeferredprepass)
12851                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12852         }
12853         else
12854         {
12855                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12856                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12857         }
12858         CHECKGLERROR
12859 }
12860
12861 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12862 {
12863         int i, j;
12864         texture_t *texture;
12865         // break the surface list down into batches by texture and use of lightmapping
12866         for (i = 0;i < numsurfaces;i = j)
12867         {
12868                 j = i + 1;
12869                 // texture is the base texture pointer, rsurface.texture is the
12870                 // current frame/skin the texture is directing us to use (for example
12871                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12872                 // use skin 1 instead)
12873                 texture = surfacelist[i]->texture;
12874                 rsurface.texture = R_GetCurrentTexture(texture);
12875                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12876                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12877                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12878                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12879                 {
12880                         // if this texture is not the kind we want, skip ahead to the next one
12881                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12882                                 ;
12883                         continue;
12884                 }
12885                 // simply scan ahead until we find a different texture or lightmap state
12886                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12887                         ;
12888                 // render the range of surfaces
12889                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12890         }
12891 }
12892
12893 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12894 {
12895         CHECKGLERROR
12896         if (depthonly)
12897                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12898         else if (prepass)
12899         {
12900                 if (!rsurface.texture->currentnumlayers)
12901                         return;
12902                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12903                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12904                 else
12905                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12906         }
12907         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12908                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12909         else if (!rsurface.texture->currentnumlayers)
12910                 return;
12911         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12912         {
12913                 // in the deferred case, transparent surfaces were queued during prepass
12914                 if (!r_shadow_usingdeferredprepass)
12915                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12916         }
12917         else
12918         {
12919                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12920                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12921         }
12922         CHECKGLERROR
12923 }
12924
12925 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12926 {
12927         int i, j;
12928         texture_t *texture;
12929         // break the surface list down into batches by texture and use of lightmapping
12930         for (i = 0;i < numsurfaces;i = j)
12931         {
12932                 j = i + 1;
12933                 // texture is the base texture pointer, rsurface.texture is the
12934                 // current frame/skin the texture is directing us to use (for example
12935                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12936                 // use skin 1 instead)
12937                 texture = surfacelist[i]->texture;
12938                 rsurface.texture = R_GetCurrentTexture(texture);
12939                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12940                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12941                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12942                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12943                 {
12944                         // if this texture is not the kind we want, skip ahead to the next one
12945                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12946                                 ;
12947                         continue;
12948                 }
12949                 // simply scan ahead until we find a different texture or lightmap state
12950                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12951                         ;
12952                 // render the range of surfaces
12953                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12954         }
12955 }
12956
12957 float locboxvertex3f[6*4*3] =
12958 {
12959         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12960         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12961         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12962         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12963         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12964         1,0,0, 0,0,0, 0,1,0, 1,1,0
12965 };
12966
12967 unsigned short locboxelements[6*2*3] =
12968 {
12969          0, 1, 2, 0, 2, 3,
12970          4, 5, 6, 4, 6, 7,
12971          8, 9,10, 8,10,11,
12972         12,13,14, 12,14,15,
12973         16,17,18, 16,18,19,
12974         20,21,22, 20,22,23
12975 };
12976
12977 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12978 {
12979         int i, j;
12980         cl_locnode_t *loc = (cl_locnode_t *)ent;
12981         vec3_t mins, size;
12982         float vertex3f[6*4*3];
12983         CHECKGLERROR
12984         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12985         GL_DepthMask(false);
12986         GL_DepthRange(0, 1);
12987         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12988         GL_DepthTest(true);
12989         GL_CullFace(GL_NONE);
12990         R_EntityMatrix(&identitymatrix);
12991
12992         R_Mesh_ResetTextureState();
12993
12994         i = surfacelist[0];
12995         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12996                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12997                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12998                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12999
13000         if (VectorCompare(loc->mins, loc->maxs))
13001         {
13002                 VectorSet(size, 2, 2, 2);
13003                 VectorMA(loc->mins, -0.5f, size, mins);
13004         }
13005         else
13006         {
13007                 VectorCopy(loc->mins, mins);
13008                 VectorSubtract(loc->maxs, loc->mins, size);
13009         }
13010
13011         for (i = 0;i < 6*4*3;)
13012                 for (j = 0;j < 3;j++, i++)
13013                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13014
13015         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13016         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13017         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13018 }
13019
13020 void R_DrawLocs(void)
13021 {
13022         int index;
13023         cl_locnode_t *loc, *nearestloc;
13024         vec3_t center;
13025         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13026         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13027         {
13028                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13029                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13030         }
13031 }
13032
13033 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13034 {
13035         if (decalsystem->decals)
13036                 Mem_Free(decalsystem->decals);
13037         memset(decalsystem, 0, sizeof(*decalsystem));
13038 }
13039
13040 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)
13041 {
13042         tridecal_t *decal;
13043         tridecal_t *decals;
13044         int i;
13045
13046         // expand or initialize the system
13047         if (decalsystem->maxdecals <= decalsystem->numdecals)
13048         {
13049                 decalsystem_t old = *decalsystem;
13050                 qboolean useshortelements;
13051                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13052                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13053                 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)));
13054                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13055                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13056                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13057                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13058                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13059                 if (decalsystem->numdecals)
13060                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13061                 if (old.decals)
13062                         Mem_Free(old.decals);
13063                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13064                         decalsystem->element3i[i] = i;
13065                 if (useshortelements)
13066                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13067                                 decalsystem->element3s[i] = i;
13068         }
13069
13070         // grab a decal and search for another free slot for the next one
13071         decals = decalsystem->decals;
13072         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13073         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13074                 ;
13075         decalsystem->freedecal = i;
13076         if (decalsystem->numdecals <= i)
13077                 decalsystem->numdecals = i + 1;
13078
13079         // initialize the decal
13080         decal->lived = 0;
13081         decal->triangleindex = triangleindex;
13082         decal->surfaceindex = surfaceindex;
13083         decal->decalsequence = decalsequence;
13084         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13085         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13086         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13087         decal->color4ub[0][3] = 255;
13088         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13089         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13090         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13091         decal->color4ub[1][3] = 255;
13092         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13093         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13094         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13095         decal->color4ub[2][3] = 255;
13096         decal->vertex3f[0][0] = v0[0];
13097         decal->vertex3f[0][1] = v0[1];
13098         decal->vertex3f[0][2] = v0[2];
13099         decal->vertex3f[1][0] = v1[0];
13100         decal->vertex3f[1][1] = v1[1];
13101         decal->vertex3f[1][2] = v1[2];
13102         decal->vertex3f[2][0] = v2[0];
13103         decal->vertex3f[2][1] = v2[1];
13104         decal->vertex3f[2][2] = v2[2];
13105         decal->texcoord2f[0][0] = t0[0];
13106         decal->texcoord2f[0][1] = t0[1];
13107         decal->texcoord2f[1][0] = t1[0];
13108         decal->texcoord2f[1][1] = t1[1];
13109         decal->texcoord2f[2][0] = t2[0];
13110         decal->texcoord2f[2][1] = t2[1];
13111 }
13112
13113 extern cvar_t cl_decals_bias;
13114 extern cvar_t cl_decals_models;
13115 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13116 // baseparms, parms, temps
13117 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)
13118 {
13119         int cornerindex;
13120         int index;
13121         float v[9][3];
13122         const float *vertex3f;
13123         int numpoints;
13124         float points[2][9][3];
13125         float temp[3];
13126         float tc[9][2];
13127         float f;
13128         float c[9][4];
13129         const int *e;
13130
13131         e = rsurface.modelelement3i + 3*triangleindex;
13132
13133         vertex3f = rsurface.modelvertex3f;
13134
13135         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13136         {
13137                 index = 3*e[cornerindex];
13138                 VectorCopy(vertex3f + index, v[cornerindex]);
13139         }
13140         // cull backfaces
13141         //TriangleNormal(v[0], v[1], v[2], normal);
13142         //if (DotProduct(normal, localnormal) < 0.0f)
13143         //      continue;
13144         // clip by each of the box planes formed from the projection matrix
13145         // if anything survives, we emit the decal
13146         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]);
13147         if (numpoints < 3)
13148                 return;
13149         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]);
13150         if (numpoints < 3)
13151                 return;
13152         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]);
13153         if (numpoints < 3)
13154                 return;
13155         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]);
13156         if (numpoints < 3)
13157                 return;
13158         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]);
13159         if (numpoints < 3)
13160                 return;
13161         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]);
13162         if (numpoints < 3)
13163                 return;
13164         // some part of the triangle survived, so we have to accept it...
13165         if (dynamic)
13166         {
13167                 // dynamic always uses the original triangle
13168                 numpoints = 3;
13169                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13170                 {
13171                         index = 3*e[cornerindex];
13172                         VectorCopy(vertex3f + index, v[cornerindex]);
13173                 }
13174         }
13175         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13176         {
13177                 // convert vertex positions to texcoords
13178                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13179                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13180                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13181                 // calculate distance fade from the projection origin
13182                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13183                 f = bound(0.0f, f, 1.0f);
13184                 c[cornerindex][0] = r * f;
13185                 c[cornerindex][1] = g * f;
13186                 c[cornerindex][2] = b * f;
13187                 c[cornerindex][3] = 1.0f;
13188                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13189         }
13190         if (dynamic)
13191                 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);
13192         else
13193                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13194                         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);
13195 }
13196 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)
13197 {
13198         matrix4x4_t projection;
13199         decalsystem_t *decalsystem;
13200         qboolean dynamic;
13201         dp_model_t *model;
13202         const msurface_t *surface;
13203         const msurface_t *surfaces;
13204         const int *surfacelist;
13205         const texture_t *texture;
13206         int numtriangles;
13207         int numsurfacelist;
13208         int surfacelistindex;
13209         int surfaceindex;
13210         int triangleindex;
13211         float localorigin[3];
13212         float localnormal[3];
13213         float localmins[3];
13214         float localmaxs[3];
13215         float localsize;
13216         //float normal[3];
13217         float planes[6][4];
13218         float angles[3];
13219         bih_t *bih;
13220         int bih_triangles_count;
13221         int bih_triangles[256];
13222         int bih_surfaces[256];
13223
13224         decalsystem = &ent->decalsystem;
13225         model = ent->model;
13226         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13227         {
13228                 R_DecalSystem_Reset(&ent->decalsystem);
13229                 return;
13230         }
13231
13232         if (!model->brush.data_leafs && !cl_decals_models.integer)
13233         {
13234                 if (decalsystem->model)
13235                         R_DecalSystem_Reset(decalsystem);
13236                 return;
13237         }
13238
13239         if (decalsystem->model != model)
13240                 R_DecalSystem_Reset(decalsystem);
13241         decalsystem->model = model;
13242
13243         RSurf_ActiveModelEntity(ent, false, false, false);
13244
13245         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13246         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13247         VectorNormalize(localnormal);
13248         localsize = worldsize*rsurface.inversematrixscale;
13249         localmins[0] = localorigin[0] - localsize;
13250         localmins[1] = localorigin[1] - localsize;
13251         localmins[2] = localorigin[2] - localsize;
13252         localmaxs[0] = localorigin[0] + localsize;
13253         localmaxs[1] = localorigin[1] + localsize;
13254         localmaxs[2] = localorigin[2] + localsize;
13255
13256         //VectorCopy(localnormal, planes[4]);
13257         //VectorVectors(planes[4], planes[2], planes[0]);
13258         AnglesFromVectors(angles, localnormal, NULL, false);
13259         AngleVectors(angles, planes[0], planes[2], planes[4]);
13260         VectorNegate(planes[0], planes[1]);
13261         VectorNegate(planes[2], planes[3]);
13262         VectorNegate(planes[4], planes[5]);
13263         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13264         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13265         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13266         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13267         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13268         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13269
13270 #if 1
13271 // works
13272 {
13273         matrix4x4_t forwardprojection;
13274         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13275         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13276 }
13277 #else
13278 // broken
13279 {
13280         float projectionvector[4][3];
13281         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13282         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13283         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13284         projectionvector[0][0] = planes[0][0] * ilocalsize;
13285         projectionvector[0][1] = planes[1][0] * ilocalsize;
13286         projectionvector[0][2] = planes[2][0] * ilocalsize;
13287         projectionvector[1][0] = planes[0][1] * ilocalsize;
13288         projectionvector[1][1] = planes[1][1] * ilocalsize;
13289         projectionvector[1][2] = planes[2][1] * ilocalsize;
13290         projectionvector[2][0] = planes[0][2] * ilocalsize;
13291         projectionvector[2][1] = planes[1][2] * ilocalsize;
13292         projectionvector[2][2] = planes[2][2] * ilocalsize;
13293         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13294         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13295         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13296         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13297 }
13298 #endif
13299
13300         dynamic = model->surfmesh.isanimated;
13301         numsurfacelist = model->nummodelsurfaces;
13302         surfacelist = model->sortedmodelsurfaces;
13303         surfaces = model->data_surfaces;
13304
13305         bih = NULL;
13306         bih_triangles_count = -1;
13307         if(!dynamic)
13308         {
13309                 if(model->render_bih.numleafs)
13310                         bih = &model->render_bih;
13311                 else if(model->collision_bih.numleafs)
13312                         bih = &model->collision_bih;
13313         }
13314         if(bih)
13315                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13316         if(bih_triangles_count == 0)
13317                 return;
13318         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13319                 return;
13320         if(bih_triangles_count > 0)
13321         {
13322                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13323                 {
13324                         surfaceindex = bih_surfaces[triangleindex];
13325                         surface = surfaces + surfaceindex;
13326                         texture = surface->texture;
13327                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13328                                 continue;
13329                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13330                                 continue;
13331                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13332                 }
13333         }
13334         else
13335         {
13336                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13337                 {
13338                         surfaceindex = surfacelist[surfacelistindex];
13339                         surface = surfaces + surfaceindex;
13340                         // check cull box first because it rejects more than any other check
13341                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13342                                 continue;
13343                         // skip transparent surfaces
13344                         texture = surface->texture;
13345                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13346                                 continue;
13347                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13348                                 continue;
13349                         numtriangles = surface->num_triangles;
13350                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13351                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13352                 }
13353         }
13354 }
13355
13356 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13357 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)
13358 {
13359         int renderentityindex;
13360         float worldmins[3];
13361         float worldmaxs[3];
13362         entity_render_t *ent;
13363
13364         if (!cl_decals_newsystem.integer)
13365                 return;
13366
13367         worldmins[0] = worldorigin[0] - worldsize;
13368         worldmins[1] = worldorigin[1] - worldsize;
13369         worldmins[2] = worldorigin[2] - worldsize;
13370         worldmaxs[0] = worldorigin[0] + worldsize;
13371         worldmaxs[1] = worldorigin[1] + worldsize;
13372         worldmaxs[2] = worldorigin[2] + worldsize;
13373
13374         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13375
13376         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13377         {
13378                 ent = r_refdef.scene.entities[renderentityindex];
13379                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13380                         continue;
13381
13382                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13383         }
13384 }
13385
13386 typedef struct r_decalsystem_splatqueue_s
13387 {
13388         vec3_t worldorigin;
13389         vec3_t worldnormal;
13390         float color[4];
13391         float tcrange[4];
13392         float worldsize;
13393         int decalsequence;
13394 }
13395 r_decalsystem_splatqueue_t;
13396
13397 int r_decalsystem_numqueued = 0;
13398 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13399
13400 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)
13401 {
13402         r_decalsystem_splatqueue_t *queue;
13403
13404         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13405                 return;
13406
13407         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13408         VectorCopy(worldorigin, queue->worldorigin);
13409         VectorCopy(worldnormal, queue->worldnormal);
13410         Vector4Set(queue->color, r, g, b, a);
13411         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13412         queue->worldsize = worldsize;
13413         queue->decalsequence = cl.decalsequence++;
13414 }
13415
13416 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13417 {
13418         int i;
13419         r_decalsystem_splatqueue_t *queue;
13420
13421         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13422                 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);
13423         r_decalsystem_numqueued = 0;
13424 }
13425
13426 extern cvar_t cl_decals_max;
13427 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13428 {
13429         int i;
13430         decalsystem_t *decalsystem = &ent->decalsystem;
13431         int numdecals;
13432         int killsequence;
13433         tridecal_t *decal;
13434         float frametime;
13435         float lifetime;
13436
13437         if (!decalsystem->numdecals)
13438                 return;
13439
13440         if (r_showsurfaces.integer)
13441                 return;
13442
13443         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13444         {
13445                 R_DecalSystem_Reset(decalsystem);
13446                 return;
13447         }
13448
13449         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13450         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13451
13452         if (decalsystem->lastupdatetime)
13453                 frametime = (cl.time - decalsystem->lastupdatetime);
13454         else
13455                 frametime = 0;
13456         decalsystem->lastupdatetime = cl.time;
13457         decal = decalsystem->decals;
13458         numdecals = decalsystem->numdecals;
13459
13460         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13461         {
13462                 if (decal->color4ub[0][3])
13463                 {
13464                         decal->lived += frametime;
13465                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13466                         {
13467                                 memset(decal, 0, sizeof(*decal));
13468                                 if (decalsystem->freedecal > i)
13469                                         decalsystem->freedecal = i;
13470                         }
13471                 }
13472         }
13473         decal = decalsystem->decals;
13474         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13475                 numdecals--;
13476
13477         // collapse the array by shuffling the tail decals into the gaps
13478         for (;;)
13479         {
13480                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13481                         decalsystem->freedecal++;
13482                 if (decalsystem->freedecal == numdecals)
13483                         break;
13484                 decal[decalsystem->freedecal] = decal[--numdecals];
13485         }
13486
13487         decalsystem->numdecals = numdecals;
13488
13489         if (numdecals <= 0)
13490         {
13491                 // if there are no decals left, reset decalsystem
13492                 R_DecalSystem_Reset(decalsystem);
13493         }
13494 }
13495
13496 extern skinframe_t *decalskinframe;
13497 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13498 {
13499         int i;
13500         decalsystem_t *decalsystem = &ent->decalsystem;
13501         int numdecals;
13502         tridecal_t *decal;
13503         float faderate;
13504         float alpha;
13505         float *v3f;
13506         float *c4f;
13507         float *t2f;
13508         const int *e;
13509         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13510         int numtris = 0;
13511
13512         numdecals = decalsystem->numdecals;
13513         if (!numdecals)
13514                 return;
13515
13516         if (r_showsurfaces.integer)
13517                 return;
13518
13519         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13520         {
13521                 R_DecalSystem_Reset(decalsystem);
13522                 return;
13523         }
13524
13525         // if the model is static it doesn't matter what value we give for
13526         // wantnormals and wanttangents, so this logic uses only rules applicable
13527         // to a model, knowing that they are meaningless otherwise
13528         if (ent == r_refdef.scene.worldentity)
13529                 RSurf_ActiveWorldEntity();
13530         else
13531                 RSurf_ActiveModelEntity(ent, false, false, false);
13532
13533         decalsystem->lastupdatetime = cl.time;
13534         decal = decalsystem->decals;
13535
13536         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13537
13538         // update vertex positions for animated models
13539         v3f = decalsystem->vertex3f;
13540         c4f = decalsystem->color4f;
13541         t2f = decalsystem->texcoord2f;
13542         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13543         {
13544                 if (!decal->color4ub[0][3])
13545                         continue;
13546
13547                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13548                         continue;
13549
13550                 // update color values for fading decals
13551                 if (decal->lived >= cl_decals_time.value)
13552                 {
13553                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13554                         alpha *= (1.0f/255.0f);
13555                 }
13556                 else
13557                         alpha = 1.0f/255.0f;
13558
13559                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13560                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13561                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13562                 c4f[ 3] = 1;
13563                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13564                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13565                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13566                 c4f[ 7] = 1;
13567                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13568                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13569                 c4f[10] = decal->color4ub[2][2] * alpha;
13570                 c4f[11] = 1;
13571
13572                 t2f[0] = decal->texcoord2f[0][0];
13573                 t2f[1] = decal->texcoord2f[0][1];
13574                 t2f[2] = decal->texcoord2f[1][0];
13575                 t2f[3] = decal->texcoord2f[1][1];
13576                 t2f[4] = decal->texcoord2f[2][0];
13577                 t2f[5] = decal->texcoord2f[2][1];
13578
13579                 // update vertex positions for animated models
13580                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13581                 {
13582                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13583                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13584                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13585                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13586                 }
13587                 else
13588                 {
13589                         VectorCopy(decal->vertex3f[0], v3f);
13590                         VectorCopy(decal->vertex3f[1], v3f + 3);
13591                         VectorCopy(decal->vertex3f[2], v3f + 6);
13592                 }
13593
13594                 if (r_refdef.fogenabled)
13595                 {
13596                         alpha = RSurf_FogVertex(v3f);
13597                         VectorScale(c4f, alpha, c4f);
13598                         alpha = RSurf_FogVertex(v3f + 3);
13599                         VectorScale(c4f + 4, alpha, c4f + 4);
13600                         alpha = RSurf_FogVertex(v3f + 6);
13601                         VectorScale(c4f + 8, alpha, c4f + 8);
13602                 }
13603
13604                 v3f += 9;
13605                 c4f += 12;
13606                 t2f += 6;
13607                 numtris++;
13608         }
13609
13610         if (numtris > 0)
13611         {
13612                 r_refdef.stats.drawndecals += numtris;
13613
13614                 // now render the decals all at once
13615                 // (this assumes they all use one particle font texture!)
13616                 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);
13617                 R_Mesh_ResetTextureState();
13618                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13619                 GL_DepthMask(false);
13620                 GL_DepthRange(0, 1);
13621                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13622                 GL_DepthTest(true);
13623                 GL_CullFace(GL_NONE);
13624                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13625                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13626                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13627         }
13628 }
13629
13630 static void R_DrawModelDecals(void)
13631 {
13632         int i, numdecals;
13633
13634         // fade faster when there are too many decals
13635         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13636         for (i = 0;i < r_refdef.scene.numentities;i++)
13637                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13638
13639         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13640         for (i = 0;i < r_refdef.scene.numentities;i++)
13641                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13642                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13643
13644         R_DecalSystem_ApplySplatEntitiesQueue();
13645
13646         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13647         for (i = 0;i < r_refdef.scene.numentities;i++)
13648                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13649
13650         r_refdef.stats.totaldecals += numdecals;
13651
13652         if (r_showsurfaces.integer)
13653                 return;
13654
13655         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13656
13657         for (i = 0;i < r_refdef.scene.numentities;i++)
13658         {
13659                 if (!r_refdef.viewcache.entityvisible[i])
13660                         continue;
13661                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13662                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13663         }
13664 }
13665
13666 extern cvar_t mod_collision_bih;
13667 void R_DrawDebugModel(void)
13668 {
13669         entity_render_t *ent = rsurface.entity;
13670         int i, j, k, l, flagsmask;
13671         const msurface_t *surface;
13672         dp_model_t *model = ent->model;
13673         vec3_t v;
13674
13675         switch(vid.renderpath)
13676         {
13677         case RENDERPATH_GL11:
13678         case RENDERPATH_GL13:
13679         case RENDERPATH_GL20:
13680         case RENDERPATH_CGGL:
13681                 break;
13682         case RENDERPATH_D3D9:
13683                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13684                 return;
13685         case RENDERPATH_D3D10:
13686                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13687                 return;
13688         case RENDERPATH_D3D11:
13689                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13690                 return;
13691         }
13692
13693         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13694
13695         R_Mesh_ResetTextureState();
13696         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13697         GL_DepthRange(0, 1);
13698         GL_DepthTest(!r_showdisabledepthtest.integer);
13699         GL_DepthMask(false);
13700         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13701
13702         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13703         {
13704                 int triangleindex;
13705                 int bihleafindex;
13706                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13707                 const q3mbrush_t *brush;
13708                 const bih_t *bih = &model->collision_bih;
13709                 const bih_leaf_t *bihleaf;
13710                 float vertex3f[3][3];
13711                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13712                 cullbox = false;
13713                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13714                 {
13715                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13716                                 continue;
13717                         switch (bihleaf->type)
13718                         {
13719                         case BIH_BRUSH:
13720                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13721                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13722                                 {
13723                                         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);
13724                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13725                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13726                                 }
13727                                 break;
13728                         case BIH_COLLISIONTRIANGLE:
13729                                 triangleindex = bihleaf->itemindex;
13730                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13731                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13732                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13733                                 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);
13734                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13735                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13736                                 break;
13737                         case BIH_RENDERTRIANGLE:
13738                                 triangleindex = bihleaf->itemindex;
13739                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13740                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13741                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13742                                 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);
13743                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13744                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13745                                 break;
13746                         }
13747                 }
13748         }
13749
13750         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13751
13752         if (r_showtris.integer || r_shownormals.integer)
13753         {
13754                 if (r_showdisabledepthtest.integer)
13755                 {
13756                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13757                         GL_DepthMask(false);
13758                 }
13759                 else
13760                 {
13761                         GL_BlendFunc(GL_ONE, GL_ZERO);
13762                         GL_DepthMask(true);
13763                 }
13764                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13765                 {
13766                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13767                                 continue;
13768                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13769                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13770                         {
13771                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13772                                 if (r_showtris.value > 0)
13773                                 {
13774                                         if (!rsurface.texture->currentlayers->depthmask)
13775                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13776                                         else if (ent == r_refdef.scene.worldentity)
13777                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13778                                         else
13779                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13780                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13781                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13782                                         RSurf_DrawBatch();
13783                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13784                                         CHECKGLERROR
13785                                 }
13786                                 if (r_shownormals.value < 0)
13787                                 {
13788                                         qglBegin(GL_LINES);
13789                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13790                                         {
13791                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13792                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13793                                                 qglVertex3f(v[0], v[1], v[2]);
13794                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13795                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13796                                                 qglVertex3f(v[0], v[1], v[2]);
13797                                         }
13798                                         qglEnd();
13799                                         CHECKGLERROR
13800                                 }
13801                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13802                                 {
13803                                         qglBegin(GL_LINES);
13804                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13805                                         {
13806                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13807                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13808                                                 qglVertex3f(v[0], v[1], v[2]);
13809                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13810                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13811                                                 qglVertex3f(v[0], v[1], v[2]);
13812                                         }
13813                                         qglEnd();
13814                                         CHECKGLERROR
13815                                         qglBegin(GL_LINES);
13816                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13817                                         {
13818                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13819                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13820                                                 qglVertex3f(v[0], v[1], v[2]);
13821                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13822                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13823                                                 qglVertex3f(v[0], v[1], v[2]);
13824                                         }
13825                                         qglEnd();
13826                                         CHECKGLERROR
13827                                         qglBegin(GL_LINES);
13828                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13829                                         {
13830                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13831                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13832                                                 qglVertex3f(v[0], v[1], v[2]);
13833                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13834                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13835                                                 qglVertex3f(v[0], v[1], v[2]);
13836                                         }
13837                                         qglEnd();
13838                                         CHECKGLERROR
13839                                 }
13840                         }
13841                 }
13842                 rsurface.texture = NULL;
13843         }
13844 }
13845
13846 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13847 int r_maxsurfacelist = 0;
13848 const msurface_t **r_surfacelist = NULL;
13849 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13850 {
13851         int i, j, endj, flagsmask;
13852         dp_model_t *model = r_refdef.scene.worldmodel;
13853         msurface_t *surfaces;
13854         unsigned char *update;
13855         int numsurfacelist = 0;
13856         if (model == NULL)
13857                 return;
13858
13859         if (r_maxsurfacelist < model->num_surfaces)
13860         {
13861                 r_maxsurfacelist = model->num_surfaces;
13862                 if (r_surfacelist)
13863                         Mem_Free((msurface_t**)r_surfacelist);
13864                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13865         }
13866
13867         RSurf_ActiveWorldEntity();
13868
13869         surfaces = model->data_surfaces;
13870         update = model->brushq1.lightmapupdateflags;
13871
13872         // update light styles on this submodel
13873         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13874         {
13875                 model_brush_lightstyleinfo_t *style;
13876                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13877                 {
13878                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13879                         {
13880                                 int *list = style->surfacelist;
13881                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13882                                 for (j = 0;j < style->numsurfaces;j++)
13883                                         update[list[j]] = true;
13884                         }
13885                 }
13886         }
13887
13888         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13889
13890         if (debug)
13891         {
13892                 R_DrawDebugModel();
13893                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13894                 return;
13895         }
13896
13897         rsurface.lightmaptexture = NULL;
13898         rsurface.deluxemaptexture = NULL;
13899         rsurface.uselightmaptexture = false;
13900         rsurface.texture = NULL;
13901         rsurface.rtlight = NULL;
13902         numsurfacelist = 0;
13903         // add visible surfaces to draw list
13904         for (i = 0;i < model->nummodelsurfaces;i++)
13905         {
13906                 j = model->sortedmodelsurfaces[i];
13907                 if (r_refdef.viewcache.world_surfacevisible[j])
13908                         r_surfacelist[numsurfacelist++] = surfaces + j;
13909         }
13910         // update lightmaps if needed
13911         if (model->brushq1.firstrender)
13912         {
13913                 model->brushq1.firstrender = false;
13914                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13915                         if (update[j])
13916                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13917         }
13918         else if (update)
13919         {
13920                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13921                         if (r_refdef.viewcache.world_surfacevisible[j])
13922                                 if (update[j])
13923                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13924         }
13925         // don't do anything if there were no surfaces
13926         if (!numsurfacelist)
13927         {
13928                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13929                 return;
13930         }
13931         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13932         GL_AlphaTest(false);
13933
13934         // add to stats if desired
13935         if (r_speeds.integer && !skysurfaces && !depthonly)
13936         {
13937                 r_refdef.stats.world_surfaces += numsurfacelist;
13938                 for (j = 0;j < numsurfacelist;j++)
13939                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13940         }
13941
13942         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13943 }
13944
13945 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13946 {
13947         int i, j, endj, flagsmask;
13948         dp_model_t *model = ent->model;
13949         msurface_t *surfaces;
13950         unsigned char *update;
13951         int numsurfacelist = 0;
13952         if (model == NULL)
13953                 return;
13954
13955         if (r_maxsurfacelist < model->num_surfaces)
13956         {
13957                 r_maxsurfacelist = model->num_surfaces;
13958                 if (r_surfacelist)
13959                         Mem_Free((msurface_t **)r_surfacelist);
13960                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13961         }
13962
13963         // if the model is static it doesn't matter what value we give for
13964         // wantnormals and wanttangents, so this logic uses only rules applicable
13965         // to a model, knowing that they are meaningless otherwise
13966         if (ent == r_refdef.scene.worldentity)
13967                 RSurf_ActiveWorldEntity();
13968         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13969                 RSurf_ActiveModelEntity(ent, false, false, false);
13970         else if (prepass)
13971                 RSurf_ActiveModelEntity(ent, true, true, true);
13972         else if (depthonly)
13973         {
13974                 switch (vid.renderpath)
13975                 {
13976                 case RENDERPATH_GL20:
13977                 case RENDERPATH_CGGL:
13978                 case RENDERPATH_D3D9:
13979                 case RENDERPATH_D3D10:
13980                 case RENDERPATH_D3D11:
13981                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13982                         break;
13983                 case RENDERPATH_GL13:
13984                 case RENDERPATH_GL11:
13985                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13986                         break;
13987                 }
13988         }
13989         else
13990         {
13991                 switch (vid.renderpath)
13992                 {
13993                 case RENDERPATH_GL20:
13994                 case RENDERPATH_CGGL:
13995                 case RENDERPATH_D3D9:
13996                 case RENDERPATH_D3D10:
13997                 case RENDERPATH_D3D11:
13998                         RSurf_ActiveModelEntity(ent, true, true, false);
13999                         break;
14000                 case RENDERPATH_GL13:
14001                 case RENDERPATH_GL11:
14002                         RSurf_ActiveModelEntity(ent, true, false, false);
14003                         break;
14004                 }
14005         }
14006
14007         surfaces = model->data_surfaces;
14008         update = model->brushq1.lightmapupdateflags;
14009
14010         // update light styles
14011         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14012         {
14013                 model_brush_lightstyleinfo_t *style;
14014                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14015                 {
14016                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14017                         {
14018                                 int *list = style->surfacelist;
14019                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14020                                 for (j = 0;j < style->numsurfaces;j++)
14021                                         update[list[j]] = true;
14022                         }
14023                 }
14024         }
14025
14026         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14027
14028         if (debug)
14029         {
14030                 R_DrawDebugModel();
14031                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14032                 return;
14033         }
14034
14035         rsurface.lightmaptexture = NULL;
14036         rsurface.deluxemaptexture = NULL;
14037         rsurface.uselightmaptexture = false;
14038         rsurface.texture = NULL;
14039         rsurface.rtlight = NULL;
14040         numsurfacelist = 0;
14041         // add visible surfaces to draw list
14042         for (i = 0;i < model->nummodelsurfaces;i++)
14043                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14044         // don't do anything if there were no surfaces
14045         if (!numsurfacelist)
14046         {
14047                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14048                 return;
14049         }
14050         // update lightmaps if needed
14051         if (update)
14052         {
14053                 int updated = 0;
14054                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14055                 {
14056                         if (update[j])
14057                         {
14058                                 updated++;
14059                                 R_BuildLightMap(ent, surfaces + j);
14060                         }
14061                 }
14062         }
14063         if (update)
14064                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14065                         if (update[j])
14066                                 R_BuildLightMap(ent, surfaces + j);
14067         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14068         GL_AlphaTest(false);
14069
14070         // add to stats if desired
14071         if (r_speeds.integer && !skysurfaces && !depthonly)
14072         {
14073                 r_refdef.stats.entities_surfaces += numsurfacelist;
14074                 for (j = 0;j < numsurfacelist;j++)
14075                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14076         }
14077
14078         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14079 }
14080
14081 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14082 {
14083         static texture_t texture;
14084         static msurface_t surface;
14085         const msurface_t *surfacelist = &surface;
14086
14087         // fake enough texture and surface state to render this geometry
14088
14089         texture.update_lastrenderframe = -1; // regenerate this texture
14090         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14091         texture.currentskinframe = skinframe;
14092         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14093         texture.offsetmapping = OFFSETMAPPING_OFF;
14094         texture.offsetscale = 1;
14095         texture.specularscalemod = 1;
14096         texture.specularpowermod = 1;
14097
14098         surface.texture = &texture;
14099         surface.num_triangles = numtriangles;
14100         surface.num_firsttriangle = firsttriangle;
14101         surface.num_vertices = numvertices;
14102         surface.num_firstvertex = firstvertex;
14103
14104         // now render it
14105         rsurface.texture = R_GetCurrentTexture(surface.texture);
14106         rsurface.lightmaptexture = NULL;
14107         rsurface.deluxemaptexture = NULL;
14108         rsurface.uselightmaptexture = false;
14109         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14110 }
14111
14112 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)
14113 {
14114         static msurface_t surface;
14115         const msurface_t *surfacelist = &surface;
14116
14117         // fake enough texture and surface state to render this geometry
14118
14119         surface.texture = texture;
14120         surface.num_triangles = numtriangles;
14121         surface.num_firsttriangle = firsttriangle;
14122         surface.num_vertices = numvertices;
14123         surface.num_firstvertex = firstvertex;
14124
14125         // now render it
14126         rsurface.texture = R_GetCurrentTexture(surface.texture);
14127         rsurface.lightmaptexture = NULL;
14128         rsurface.deluxemaptexture = NULL;
14129         rsurface.uselightmaptexture = false;
14130         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14131 }