]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
UNMERGE
[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 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
592 "#endif\n"
593 "\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "#   extension GL_EXT_gpu_shader4 : enable\n"
597 "# endif\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "#   extension GL_ARB_texture_gather : enable\n"
600 "# else\n"
601 "#   ifdef GL_AMD_texture_texture4\n"
602 "#     extension GL_AMD_texture_texture4 : enable\n"
603 "#   endif\n"
604 "# endif\n"
605 "#endif\n"
606 "\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
609 "#endif\n"
610 "\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
613 "//#endif\n"
614 "\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
620 "//#else\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
625 "//#endif\n"
626 "\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#endif\n"
630 "\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "}\n"
637 "#endif\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
639 "\n"
640 "\n"
641 "\n"
642 "\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
649 "}\n"
650 "#endif\n"
651 "\n"
652 "#ifdef FRAGMENT_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_FragColor = gl_Color;\n"
656 "}\n"
657 "#endif\n"
658 "#else // !MODE_SHOWDEPTH\n"
659 "\n"
660 "\n"
661 "\n"
662 "\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
666 "\n"
667 "#ifdef VERTEX_SHADER\n"
668 "void main(void)\n"
669 "{\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 "#ifdef USEBLOOM\n"
673 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
674 "#endif\n"
675 "}\n"
676 "#endif\n"
677 "\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
680 "#ifdef USEBLOOM\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
683 "#endif\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
686 "#endif\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
692 "#endif\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
700 "void main(void)\n"
701 "{\n"
702 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 "#ifdef USEBLOOM\n"
704 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#endif\n"
706 "#ifdef USEVIEWTINT\n"
707 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
713 "       float sobel = 1.0;\n"
714 "       // vec2 ts = textureSize(Texture_First, 0);\n"
715 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 "       vec2 px = PixelSize;\n"
717 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
719 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
722 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
725 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
728 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#endif\n"
750 "\n"
751 "#ifdef USESATURATION\n"
752 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#endif\n"
757 "\n"
758 "#ifdef USEGAMMARAMPS\n"
759 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
762 "#endif\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_POSTPROCESS\n"
766 "\n"
767 "\n"
768 "\n"
769 "\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
773 "#endif\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
776 "#endif\n"
777 "#ifdef VERTEX_SHADER\n"
778 "void main(void)\n"
779 "{\n"
780 "       gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
783 "#endif\n"
784 "#ifdef USESPECULAR\n"
785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
786 "#endif\n"
787 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
788 "}\n"
789 "#endif\n"
790 "\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
797 "#endif\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#endif\n"
805 "\n"
806 "#ifdef USESPECULAR\n"
807 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 "       gl_FragColor *= tex2;\n"
810 "# endif\n"
811 "# ifdef USEGLOW\n"
812 "       gl_FragColor += tex2;\n"
813 "# endif\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
816 "# endif\n"
817 "#endif\n"
818 "}\n"
819 "#endif\n"
820 "#else // !MODE_GENERIC\n"
821 "\n"
822 "\n"
823 "\n"
824 "\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
828 "void main(void)\n"
829 "{\n"
830 "       gl_FrontColor = gl_Color;\n"
831 "       TexCoord = gl_MultiTexCoord0.xy;\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "}\n"
834 "#endif\n"
835 "\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
839 "\n"
840 "void main(void)\n"
841 "{\n"
842 "       int i;\n"
843 "       vec2 tc = TexCoord;\n"
844 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 "       tc += BloomBlur_Parameters.xy;\n"
846 "       for (i = 1;i < SAMPLES;i++)\n"
847 "       {\n"
848 "               color += texture2D(Texture_First, tc).rgb;\n"
849 "               tc += BloomBlur_Parameters.xy;\n"
850 "       }\n"
851 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
860 "\n"
861 "void main(void)\n"
862 "{\n"
863 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 "       ModelViewProjectionPosition = gl_Position;\n"
866 "}\n"
867 "#endif\n"
868 "\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
873 "\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 "       // FIXME temporary hack to detect the case that the reflection\n"
889 "       // gets blackened at edges due to leaving the area that contains actual\n"
890 "       // content.\n"
891 "       // Remove this 'ack once we have a better way to stop this thing from\n"
892 "       // 'appening.\n"
893 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
899 "}\n"
900 "#endif\n"
901 "#else // !MODE_REFRACTION\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
913 "\n"
914 "void main(void)\n"
915 "{\n"
916 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 "       ModelViewProjectionPosition = gl_Position;\n"
923 "}\n"
924 "#endif\n"
925 "\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
930 "\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
938 "\n"
939 "void main(void)\n"
940 "{\n"
941 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 "       // FIXME temporary hack to detect the case that the reflection\n"
947 "       // gets blackened at edges due to leaving the area that contains actual\n"
948 "       // content.\n"
949 "       // Remove this 'ack once we have a better way to stop this thing from\n"
950 "       // 'appening.\n"
951 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
963 "}\n"
964 "#endif\n"
965 "#else // !MODE_WATER\n"
966 "\n"
967 "\n"
968 "\n"
969 "\n"
970 "// common definitions between vertex shader and fragment shader:\n"
971 "\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
975 "#endif\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
982 "#endif\n"
983 "\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
986 "#endif\n"
987 "\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
990 "#endif\n"
991 "#ifdef USEFOG\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
993 "#endif\n"
994 "\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1003 "#endif\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1011 "#endif\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1015 "#endif\n"
1016 "uniform vec4 FogPlane;\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1020 "#endif\n"
1021 "\n"
1022 "\n"
1023 "\n"
1024 "\n"
1025 "\n"
1026 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1027 "\n"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1030 "\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1034 "#ifdef USEGLOW\n"
1035 "uniform sampler2D Texture_Glow;\n"
1036 "#endif\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1041 "#ifdef USEGLOW\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1043 "#endif\n"
1044 "#endif\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1048 "#endif\n"
1049 "#ifdef USEFOG\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1052 "#endif\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1054 "#endif\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1057 "#endif\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1060 "#endif\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1068 "#endif\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1072 "#endif\n"
1073 "\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1077 "\n"
1078 "#ifdef USEFOG\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1083 "{\n"
1084 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1086 "       float fogfrac;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 "       fogfrac = fogheightpixel.a;\n"
1090 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1091 "#else\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1094 "# else\n"
1095 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1096 "# endif\n"
1097 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1098 "#endif\n"
1099 "}\n"
1100 "#endif\n"
1101 "\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1105 "{\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 "       // 14 sample relief mapping: linear search and then binary search\n"
1108 "       // this basically steps forward a small amount repeatedly until it finds\n"
1109 "       // itself inside solid, then jitters forward and back using decreasing\n"
1110 "       // amounts to find the impact\n"
1111 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 "       vec3 RT = vec3(TexCoord, 1);\n"
1115 "       OffsetVector *= 0.1;\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1118 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1126 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1127 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1128 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1130 "       return RT.xy;\n"
1131 "#else\n"
1132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 "       // this basically moves forward the full distance, and then backs up based\n"
1134 "       // on height of samples\n"
1135 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 "       TexCoord += OffsetVector;\n"
1139 "       OffsetVector *= 0.333;\n"
1140 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 "       return TexCoord;\n"
1144 "#endif\n"
1145 "}\n"
1146 "#endif // USEOFFSETMAPPING\n"
1147 "\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1151 "#endif\n"
1152 "\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1158 "# else\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1160 "# endif\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1166 "# else\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1168 "# endif\n"
1169 "#endif\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1178 "# else\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1180 "# endif\n"
1181 "#endif\n"
1182 "\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1186 "#endif\n"
1187 "\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1191 "# else\n"
1192 "#  ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1194 "{\n"
1195 "       vec3 adir = abs(dir);\n"
1196 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1199 "}\n"
1200 "#  else\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       float ma = adir.z;\n"
1205 "       vec4 proj = vec4(dir, 2.5);\n"
1206 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1210 "}\n"
1211 "#  endif\n"
1212 "# endif\n"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1217 "{\n"
1218 "       vec3 adir = abs(dir);\n"
1219 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1220 "}\n"
1221 "#endif\n"
1222 "\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1225 "{\n"
1226 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "       float f;\n"
1228 "#  ifdef USESHADOWSAMPLER\n"
1229 "\n"
1230 "#    ifdef USESHADOWMAPPCF\n"
1231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1233 "#    else\n"
1234 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1235 "#    endif\n"
1236 "\n"
1237 "#  else\n"
1238 "\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1244 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1245 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1246 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1247 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1249 "#      else\n"
1250 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 "       vec2 offset = fract(shadowmaptc.xy);\n"
1252 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1254 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1255 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1257 "#      endif\n"
1258 "#    else\n"
1259 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1260 "#    endif\n"
1261 "\n"
1262 "#  endif\n"
1263 "#  ifdef USESHADOWMAPORTHO\n"
1264 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1265 "#  else\n"
1266 "       return f;\n"
1267 "#  endif\n"
1268 "}\n"
1269 "# endif\n"
1270 "\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1273 "{\n"
1274 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1275 "       float f;\n"
1276 "\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "#    ifdef USESHADOWMAPPCF\n"
1279 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1280 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1282 "#    else\n"
1283 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1284 "#    endif\n"
1285 "#  else\n"
1286 "#    ifdef USESHADOWMAPPCF\n"
1287 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "#      ifdef GL_ARB_texture_gather\n"
1289 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1290 "#      else\n"
1291 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1292 "#      endif\n"
1293 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "#      if USESHADOWMAPPCF > 1\n"
1295 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1299 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1300 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1301 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1302 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1303 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1304 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 "       locols.yz += group2.ab;\n"
1307 "       hicols.yz += group8.rg;\n"
1308 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 "                               mix(locols, hicols, offset.y);\n"
1311 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 "       f = dot(cols, vec4(1.0/25.0));\n"
1314 "#      else\n"
1315 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1318 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1319 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1322 "#      endif\n"
1323 "#     else\n"
1324 "#      ifdef GL_EXT_gpu_shader4\n"
1325 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1326 "#      else\n"
1327 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1328 "#      endif\n"
1329 "#      if USESHADOWMAPPCF > 1\n"
1330 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 "       center *= ShadowMap_TextureScale;\n"
1332 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1333 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1334 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1335 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1336 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      else\n"
1339 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1342 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1343 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1345 "#      endif\n"
1346 "#     endif\n"
1347 "#    else\n"
1348 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1349 "#    endif\n"
1350 "#  endif\n"
1351 "#  ifdef USESHADOWMAPORTHO\n"
1352 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1353 "#  else\n"
1354 "       return f;\n"
1355 "#  endif\n"
1356 "}\n"
1357 "# endif\n"
1358 "\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1361 "{\n"
1362 "       // apply depth texture cubemap as light filter\n"
1363 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1364 "       float f;\n"
1365 "#  ifdef USESHADOWSAMPLER\n"
1366 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1367 "#  else\n"
1368 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1369 "#  endif\n"
1370 "       return f;\n"
1371 "}\n"
1372 "# endif\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#endif\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1386 "void main(void)\n"
1387 "{\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#endif\n"
1393 "\n"
1394 "       // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1400 "#endif\n"
1401 "\n"
1402 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "void main(void)\n"
1411 "{\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 "       // apply offsetmapping\n"
1414 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1416 "#endif\n"
1417 "\n"
1418 "#ifdef USEALPHAKILL\n"
1419 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1420 "               discard;\n"
1421 "#endif\n"
1422 "\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1433 "#else\n"
1434 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1436 "#endif\n"
1437 "\n"
1438 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1439 "}\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1442 "\n"
1443 "\n"
1444 "\n"
1445 "\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1449 "void main(void)\n"
1450 "{\n"
1451 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1465 "#endif\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1467 "void main(void)\n"
1468 "{\n"
1469 "       // calculate viewspace pixel position\n"
1470 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1471 "       vec3 position;\n"
1472 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 "       // decode viewspace pixel normal\n"
1475 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 "       // surfacenormal = pixel normal in viewspace\n"
1478 "       // LightVector = pixel to light in viewspace\n"
1479 "       // CubeVector = position in lightspace\n"
1480 "       // eyevector = pixel to view in viewspace\n"
1481 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 "       // calculate diffuse shading\n"
1485 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1487 "#endif\n"
1488 "#ifdef USESPECULAR\n"
1489 "       // calculate directional shading\n"
1490 "       vec3 eyevector = position * -1.0;\n"
1491 "#  ifdef USEEXACTSPECULARMATH\n"
1492 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1493 "#  else\n"
1494 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1496 "#  endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 "       fade *= ShadowMapCompare(CubeVector);\n"
1501 "#endif\n"
1502 "\n"
1503 "#ifdef USEDIFFUSE\n"
1504 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1505 "#else\n"
1506 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1507 "#endif\n"
1508 "#ifdef USESPECULAR\n"
1509 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1510 "#else\n"
1511 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1512 "#endif\n"
1513 "\n"
1514 "# ifdef USECUBEFILTER\n"
1515 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 "       gl_FragData[0].rgb *= cubecolor;\n"
1517 "       gl_FragData[1].rgb *= cubecolor;\n"
1518 "# endif\n"
1519 "}\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1522 "\n"
1523 "\n"
1524 "\n"
1525 "\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1530 "#endif\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1533 "#endif\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1536 "#endif\n"
1537 "void main(void)\n"
1538 "{\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 "       gl_FrontColor = gl_Color;\n"
1541 "#endif\n"
1542 "       // copy the surface texcoord\n"
1543 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1546 "#endif\n"
1547 "#ifdef USELIGHTMAP\n"
1548 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1549 "#endif\n"
1550 "\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 "       // transform vertex position into light attenuation/cubemap space\n"
1553 "       // (-1 to +1 across the light box)\n"
1554 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1555 "\n"
1556 "# ifdef USEDIFFUSE\n"
1557 "       // transform unnormalized light direction into tangent space\n"
1558 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 "       //  normalize it per pixel)\n"
1560 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1564 "# endif\n"
1565 "#endif\n"
1566 "\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1571 "#endif\n"
1572 "\n"
1573 "       // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1579 "#endif\n"
1580 "\n"
1581 "#ifdef USEFOG\n"
1582 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1584 "#endif\n"
1585 "\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1588 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1589 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1590 "#endif\n"
1591 "\n"
1592 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1594 "\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1597 "#endif\n"
1598 "\n"
1599 "#ifdef USEREFLECTION\n"
1600 "       ModelViewProjectionPosition = gl_Position;\n"
1601 "#endif\n"
1602 "}\n"
1603 "#endif // VERTEX_SHADER\n"
1604 "\n"
1605 "\n"
1606 "\n"
1607 "\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1613 "#endif\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1618 "#ifdef USEGLOW\n"
1619 "uniform myhalf3 Color_Glow;\n"
1620 "#endif\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1627 "#endif\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1632 "#endif\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1635 "#endif\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1638 "#endif\n"
1639 "void main(void)\n"
1640 "{\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 "       // apply offsetmapping\n"
1643 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1645 "#endif\n"
1646 "\n"
1647 "       // combine the diffuse textures (base, pants, shirt)\n"
1648 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 "       if (color.a < 0.5)\n"
1651 "               discard;\n"
1652 "#endif\n"
1653 "       color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1656 "#endif\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1662 "       color.a = 1.0;\n"
1663 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1664 "#endif\n"
1665 "\n"
1666 "       // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1669 "#else\n"
1670 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1671 "#endif\n"
1672 "\n"
1673 "       // get the material colors\n"
1674 "       myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1678 "# else\n"
1679 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1680 "# endif\n"
1681 "#endif\n"
1682 "\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1702 "#else\n"
1703 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1705 "#endif\n"
1706 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1707 "#endif\n"
1708 "#else\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif\n"
1711 "       color.rgb *= LightColor;\n"
1712 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1715 "#endif\n"
1716 "# ifdef USECUBEFILTER\n"
1717 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1718 "# endif\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1725 "#define SHADING\n"
1726 "#ifdef USEDIFFUSE\n"
1727 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1728 "#endif\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "       // convert modelspace light vector to tangentspace\n"
1737 "       myhalf3 lightnormal;\n"
1738 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1753 "#define SHADING\n"
1754 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1757 "#endif\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 "       color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef SHADING\n"
1776 "# ifdef USEDIFFUSE\n"
1777 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "#  ifdef USESPECULAR\n"
1779 "#   ifdef USEEXACTSPECULARMATH\n"
1780 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1781 "#   else\n"
1782 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1784 "#   endif\n"
1785 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1786 "#  else\n"
1787 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1788 "#  endif\n"
1789 "# else\n"
1790 "       color.rgb = diffusetex * Color_Ambient;\n"
1791 "# endif\n"
1792 "#endif\n"
1793 "\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEGLOW\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1807 "#else\n"
1808 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1809 "#endif\n"
1810 "#endif\n"
1811 "\n"
1812 "#ifdef USEFOG\n"
1813 "       color.rgb = FogVertex(color.rgb);\n"
1814 "#endif\n"
1815 "\n"
1816 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1817 "#ifdef USEREFLECTION\n"
1818 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 "       // FIXME temporary hack to detect the case that the reflection\n"
1823 "       // gets blackened at edges due to leaving the area that contains actual\n"
1824 "       // content.\n"
1825 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1826 "       // 'appening.\n"
1827 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1833 "#endif\n"
1834 "\n"
1835 "       gl_FragColor = vec4(color);\n"
1836 "}\n"
1837 "#endif // FRAGMENT_SHADER\n"
1838 "\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1848 ;
1849
1850 /*
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868
1869
1870
1871 =========================================================================================================================================================
1872
1873
1874
1875 =========================================================================================================================================================
1876 */
1877
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1882 "\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1886 "#endif\n"
1887 "\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1889 "# define USEFOG\n"
1890 "#endif\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1893 "#endif\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "#ifdef HLSL\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1903 "#else\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1905 "#endif\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1916 ")\n"
1917 "{\n"
1918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 "       Depth = gl_Position.z;\n"
1920 "}\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1928 ")\n"
1929 "{\n"
1930 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 "       temp.yz -= floor(temp.yz);\n"
1933 "       gl_FragColor = float4(temp,0);\n"
1934 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1935 "}\n"
1936 "#endif\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "       gl_FragColor = gl_FrontColor;\n"
1965 "}\n"
1966 "#endif\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1973 "\n"
1974 "#ifdef VERTEX_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 "#ifdef USEBLOOM\n"
1989 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1990 "#endif\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2000 "#ifdef USEBLOOM\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2002 "#endif\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2005 "#endif\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2008 "#endif\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2011 "#endif\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2020 ")\n"
2021 "{\n"
2022 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2023 "#ifdef USEBLOOM\n"
2024 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2033 "       float sobel = 1.0;\n"
2034 "       // float2 ts = textureSize(Texture_First, 0);\n"
2035 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 "       float2 px = PixelSize;\n"
2037 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2039 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2042 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2045 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2048 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2066 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2067 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef USESATURATION\n"
2072 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2103 ")\n"
2104 "{\n"
2105 "#ifdef HLSL\n"
2106 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2107 "#else\n"
2108 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2109 "#endif\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "       gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef USESPECULAR\n"
2142 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 "       gl_FragColor *= tex2;\n"
2145 "# endif\n"
2146 "# ifdef USEGLOW\n"
2147 "       gl_FragColor += tex2;\n"
2148 "# endif\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2151 "# endif\n"
2152 "#endif\n"
2153 "}\n"
2154 "#endif\n"
2155 "#else // !MODE_GENERIC\n"
2156 "\n"
2157 "\n"
2158 "\n"
2159 "\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2162 "void main\n"
2163 "(\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2169 ")\n"
2170 "{\n"
2171 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2172 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "\n"
2178 "void main\n"
2179 "(\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2184 ")\n"
2185 "{\n"
2186 "       int i;\n"
2187 "       float2 tc = TexCoord;\n"
2188 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 "       tc += BloomBlur_Parameters.xy;\n"
2190 "       for (i = 1;i < SAMPLES;i++)\n"
2191 "       {\n"
2192 "               color += tex2D(Texture_First, tc).rgb;\n"
2193 "               tc += BloomBlur_Parameters.xy;\n"
2194 "       }\n"
2195 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2196 "}\n"
2197 "#endif\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2201 "void main\n"
2202 "(\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2212 ")\n"
2213 "{\n"
2214 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 "       ModelViewProjectionPosition = gl_Position;\n"
2217 "}\n"
2218 "#endif\n"
2219 "\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2221 "void main\n"
2222 "(\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2238 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 "       // FIXME temporary hack to detect the case that the reflection\n"
2241 "       // gets blackened at edges due to leaving the area that contains actual\n"
2242 "       // content.\n"
2243 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2244 "       // 'appening.\n"
2245 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_REFRACTION\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2260 "\n"
2261 "void main\n"
2262 "(\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2275 ")\n"
2276 "{\n"
2277 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 "       ModelViewProjectionPosition = gl_Position;\n"
2284 "}\n"
2285 "#endif\n"
2286 "\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2288 "void main\n"
2289 "(\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2304 ")\n"
2305 "{\n"
2306 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2311 "       // FIXME temporary hack to detect the case that the reflection\n"
2312 "       // gets blackened at edges due to leaving the area that contains actual\n"
2313 "       // content.\n"
2314 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2315 "       // 'appening.\n"
2316 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2328 "}\n"
2329 "#endif\n"
2330 "#else // !MODE_WATER\n"
2331 "\n"
2332 "\n"
2333 "\n"
2334 "\n"
2335 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2336 "\n"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2339 "\n"
2340 "#ifdef USEFOG\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2342 "{\n"
2343 "       float fogfrac;\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 "       fogfrac = fogheightpixel.a;\n"
2347 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2348 "#else\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2351 "# else\n"
2352 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2353 "# endif\n"
2354 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2355 "#endif\n"
2356 "}\n"
2357 "#endif\n"
2358 "\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2361 "{\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 "       // 14 sample relief mapping: linear search and then binary search\n"
2364 "       // this basically steps forward a small amount repeatedly until it finds\n"
2365 "       // itself inside solid, then jitters forward and back using decreasing\n"
2366 "       // amounts to find the impact\n"
2367 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 "       float3 RT = float3(TexCoord, 1);\n"
2371 "       OffsetVector *= 0.1;\n"
2372 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2382 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2383 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2384 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2386 "       return RT.xy;\n"
2387 "#else\n"
2388 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 "       // this basically moves forward the full distance, and then backs up based\n"
2390 "       // on height of samples\n"
2391 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 "       TexCoord += OffsetVector;\n"
2395 "       OffsetVector *= 0.333;\n"
2396 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2438 "{\n"
2439 "       float3 adir = abs(dir);\n"
2440 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2441 "}\n"
2442 "#endif\n"
2443 "\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2447 "#else\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2449 "#endif\n"
2450 "{\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2453 "#else\n"
2454 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2455 "#endif\n"
2456 "       float f;\n"
2457 "#  ifdef USESHADOWSAMPLER\n"
2458 "\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2462 "#    else\n"
2463 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2464 "#    endif\n"
2465 "\n"
2466 "#  else\n"
2467 "\n"
2468 "#    ifdef USESHADOWMAPPCF\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2474 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2475 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 "       float2 offset = frac(shadowmaptc.xy);\n"
2481 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2483 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2484 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2486 "#      endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2489 "#    endif\n"
2490 "\n"
2491 "#  endif\n"
2492 "#  ifdef USESHADOWMAPORTHO\n"
2493 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2494 "#  else\n"
2495 "       return f;\n"
2496 "#  endif\n"
2497 "}\n"
2498 "# endif\n"
2499 "\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2503 "#else\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2505 "#endif\n"
2506 "{\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2509 "#else\n"
2510 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2511 "#endif\n"
2512 "       float f;\n"
2513 "\n"
2514 "#  ifdef USESHADOWSAMPLER\n"
2515 "#    ifdef USESHADOWMAPPCF\n"
2516 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2517 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2519 "#    else\n"
2520 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2521 "#    endif\n"
2522 "#  else\n"
2523 "#    ifdef USESHADOWMAPPCF\n"
2524 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "#      ifdef GL_ARB_texture_gather\n"
2526 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2529 "#      endif\n"
2530 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "#      if USESHADOWMAPPCF > 1\n"
2532 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2536 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2537 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2538 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2539 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2540 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2541 "       float4 locols = float4(group1.ab, group3.ab);\n"
2542 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2543 "       locols.yz += group2.ab;\n"
2544 "       hicols.yz += group8.rg;\n"
2545 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 "                               lerp(locols, hicols, offset.y);\n"
2548 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 "       f = dot(cols, float4(1.0/25.0));\n"
2551 "#      else\n"
2552 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2555 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2556 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2559 "#      endif\n"
2560 "#     else\n"
2561 "#      ifdef GL_EXT_gpu_shader4\n"
2562 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2563 "#      else\n"
2564 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2565 "#      endif\n"
2566 "#      if USESHADOWMAPPCF > 1\n"
2567 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 "       center *= ShadowMap_TextureScale;\n"
2569 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2570 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2571 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2572 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2573 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2575 "#      else\n"
2576 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2579 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2580 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2582 "#      endif\n"
2583 "#     endif\n"
2584 "#    else\n"
2585 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2586 "#    endif\n"
2587 "#  endif\n"
2588 "#  ifdef USESHADOWMAPORTHO\n"
2589 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2590 "#  else\n"
2591 "       return f;\n"
2592 "#  endif\n"
2593 "}\n"
2594 "# endif\n"
2595 "\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2598 "{\n"
2599 "       // apply depth texture cubemap as light filter\n"
2600 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2601 "       float f;\n"
2602 "#  ifdef USESHADOWSAMPLER\n"
2603 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2604 "#  else\n"
2605 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2606 "#  endif\n"
2607 "       return f;\n"
2608 "}\n"
2609 "# endif\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\n"
2617 "#ifdef VERTEX_SHADER\n"
2618 "void main\n"
2619 "(\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2624 "#endif\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2632 "#endif\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2636 "#endif\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#endif\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2646 ")\n"
2647 "{\n"
2648 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "#ifdef HLSL\n"
2651 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2652 "#else\n"
2653 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2654 "#endif\n"
2655 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2656 "#endif\n"
2657 "\n"
2658 "       // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2664 "#endif\n"
2665 "\n"
2666 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2670 "}\n"
2671 "#endif // VERTEX_SHADER\n"
2672 "\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2674 "void main\n"
2675 "(\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2684 "#endif\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2689 "#endif\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2692 "#endif\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2695 ")\n"
2696 "{\n"
2697 "       float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 "       // apply offsetmapping\n"
2700 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEALPHAKILL\n"
2705 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2706 "               discard;\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2719 "#else\n"
2720 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2722 "#endif\n"
2723 "\n"
2724 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2725 "}\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2728 "\n"
2729 "\n"
2730 "\n"
2731 "\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2734 "void main\n"
2735 "(\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2741 ")\n"
2742 "{\n"
2743 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2745 "}\n"
2746 "#endif // VERTEX_SHADER\n"
2747 "\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2749 "void main\n"
2750 "(\n"
2751 "#ifdef HLSL\n"
2752 "float2 Pixel : VPOS,\n"
2753 "#else\n"
2754 "float2 Pixel : WPOS,\n"
2755 "#endif\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2766 "#endif\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2770 "\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2778 "# else\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2786 "# else\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2788 "# endif\n"
2789 "#endif\n"
2790 "\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2798 "# else\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2800 "# endif\n"
2801 "#endif\n"
2802 "\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2806 "#endif\n"
2807 "\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2810 ")\n"
2811 "{\n"
2812 "       // calculate viewspace pixel position\n"
2813 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 "       float3 position;\n"
2816 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 "       // decode viewspace pixel normal\n"
2819 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 "       // surfacenormal = pixel normal in viewspace\n"
2822 "       // LightVector = pixel to light in viewspace\n"
2823 "       // CubeVector = position in lightspace\n"
2824 "       // eyevector = pixel to view in viewspace\n"
2825 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 "       // calculate diffuse shading\n"
2829 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2831 "#endif\n"
2832 "#ifdef USESPECULAR\n"
2833 "       // calculate directional shading\n"
2834 "       float3 eyevector = position * -1.0;\n"
2835 "#  ifdef USEEXACTSPECULARMATH\n"
2836 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2837 "#  else\n"
2838 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2840 "#  endif\n"
2841 "#endif\n"
2842 "\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 "       fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2847 "# endif\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2850 "# endif\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2853 "# endif\n"
2854 "\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2857 "#endif\n"
2858 "       );\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USEDIFFUSE\n"
2862 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2863 "#else\n"
2864 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2865 "#endif\n"
2866 "#ifdef USESPECULAR\n"
2867 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2868 "#else\n"
2869 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2870 "#endif\n"
2871 "\n"
2872 "# ifdef USECUBEFILTER\n"
2873 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 "       gl_FragData0.rgb *= cubecolor;\n"
2875 "       gl_FragData1.rgb *= cubecolor;\n"
2876 "# endif\n"
2877 "}\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2880 "\n"
2881 "\n"
2882 "\n"
2883 "\n"
2884 "#ifdef VERTEX_SHADER\n"
2885 "void main\n"
2886 "(\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2891 "#endif\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2897 "\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2902 "#endif\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2911 "#endif\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2915 "#endif\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2918 "#endif\n"
2919 "\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2924 "#endif\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2927 "#endif\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "#endif\n"
2931 "#ifdef USEFOG\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2933 "#endif\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2936 "#endif\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "out float4 gl_Position : POSITION\n"
2949 ")\n"
2950 "{\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2952 "#ifdef HLSL\n"
2953 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2954 "#else\n"
2955 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2956 "#endif\n"
2957 "#endif\n"
2958 "       // copy the surface texcoord\n"
2959 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2962 "#endif\n"
2963 "#ifdef USELIGHTMAP\n"
2964 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2965 "#endif\n"
2966 "\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 "       // transform vertex position into light attenuation/cubemap space\n"
2969 "       // (-1 to +1 across the light box)\n"
2970 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2971 "\n"
2972 "# ifdef USEDIFFUSE\n"
2973 "       // transform unnormalized light direction into tangent space\n"
2974 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 "       //  normalize it per pixel)\n"
2976 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2980 "# endif\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2987 "#endif\n"
2988 "\n"
2989 "       // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEFOG\n"
2998 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3004 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3005 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3006 "#endif\n"
3007 "\n"
3008 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3010 "\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USEREFLECTION\n"
3016 "       ModelViewProjectionPosition = gl_Position;\n"
3017 "#endif\n"
3018 "}\n"
3019 "#endif // VERTEX_SHADER\n"
3020 "\n"
3021 "\n"
3022 "\n"
3023 "\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3025 "void main\n"
3026 "(\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "#ifdef HLSL\n"
3029 "float2 Pixel : VPOS,\n"
3030 "#else\n"
3031 "float2 Pixel : WPOS,\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3038 "#endif\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3041 "#endif\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3044 "#endif\n"
3045 "#ifdef USEFOG\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3047 "#endif\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3050 "#endif\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3053 "#endif\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3056 "#endif\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3061 "#endif\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3064 "#endif\n"
3065 "\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3070 "#endif\n"
3071 "#ifdef USEGLOW\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3073 "#endif\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3079 "#endif\n"
3080 "#ifdef USEGLOW\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3082 "#endif\n"
3083 "#endif\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3087 "#endif\n"
3088 "#ifdef USEFOG\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3091 "#endif\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3094 "#endif\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3097 "#endif\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3105 "#endif\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3114 "#endif\n"
3115 "#ifdef USEFOG\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3120 "#endif\n"
3121 "\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3130 "#endif\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3135 "#ifdef USEGLOW\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3137 "#endif\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3144 "#endif\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3149 "#endif\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3152 "#endif\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3155 "#endif\n"
3156 "\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3160 "#endif\n"
3161 "\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3163 "\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3167 "# else\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3169 "# endif\n"
3170 "#endif\n"
3171 "\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3175 "# else\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3177 "# endif\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3182 "#endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3187 "# else\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3189 "# endif\n"
3190 "#endif\n"
3191 "\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3195 "#endif\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3197 "\n"
3198 "out float4 gl_FragColor : COLOR\n"
3199 ")\n"
3200 "{\n"
3201 "       float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3204 "#endif\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 "       // apply offsetmapping\n"
3207 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3209 "#endif\n"
3210 "\n"
3211 "       // combine the diffuse textures (base, pants, shirt)\n"
3212 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 "       if (color.a < 0.5)\n"
3215 "               discard;\n"
3216 "#endif\n"
3217 "       color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3220 "#endif\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3226 "       color.a = 1.0;\n"
3227 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3228 "#endif\n"
3229 "\n"
3230 "       // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3233 "#else\n"
3234 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3235 "#endif\n"
3236 "\n"
3237 "       // get the material colors\n"
3238 "       half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3242 "# else\n"
3243 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3244 "# endif\n"
3245 "#endif\n"
3246 "\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3252 "#endif\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 "       // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 "       half3 lightnormal = half3(normalize(LightVector));\n"
3261 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3266 "#else\n"
3267 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3269 "#endif\n"
3270 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3271 "#endif\n"
3272 "#else\n"
3273 "       color.rgb = diffusetex * Color_Ambient;\n"
3274 "#endif\n"
3275 "       color.rgb *= LightColor;\n"
3276 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3281 "# endif\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3284 "# endif\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3287 "# endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3291 "#endif\n"
3292 "       ));\n"
3293 "\n"
3294 "#endif\n"
3295 "# ifdef USECUBEFILTER\n"
3296 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3297 "# endif\n"
3298 "\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3305 "#else\n"
3306 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "//     color.r = half(shadowmaptc.z);\n"
3314 "#endif\n"
3315 "//     color.r = 1;\n"
3316 "#endif\n"
3317 "//     color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3319 "\n"
3320 "\n"
3321 "\n"
3322 "\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3324 "#define SHADING\n"
3325 "#ifdef USEDIFFUSE\n"
3326 "       half3 lightnormal = half3(normalize(LightVector));\n"
3327 "#endif\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3331 "#define SHADING\n"
3332 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 "       // convert modelspace light vector to tangentspace\n"
3336 "       half3 lightnormal;\n"
3337 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3352 "#define SHADING\n"
3353 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3356 "#endif\n"
3357 "\n"
3358 "\n"
3359 "\n"
3360 "\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 "       color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3370 "\n"
3371 "\n"
3372 "\n"
3373 "\n"
3374 "#ifdef SHADING\n"
3375 "# ifdef USEDIFFUSE\n"
3376 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "#  ifdef USESPECULAR\n"
3378 "#   ifdef USEEXACTSPECULARMATH\n"
3379 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3380 "#   else\n"
3381 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3383 "#   endif\n"
3384 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3385 "#  else\n"
3386 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3387 "#  endif\n"
3388 "# else\n"
3389 "       color.rgb = diffusetex * Color_Ambient;\n"
3390 "# endif\n"
3391 "#endif\n"
3392 "\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3397 "# endif\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3400 "# endif\n"
3401 "       );\n"
3402 "#endif\n"
3403 "\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef USEGLOW\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3413 "#else\n"
3414 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3415 "#endif\n"
3416 "#endif\n"
3417 "\n"
3418 "#ifdef USEFOG\n"
3419 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3420 "#endif\n"
3421 "\n"
3422 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3423 "#ifdef USEREFLECTION\n"
3424 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 "       // FIXME temporary hack to detect the case that the reflection\n"
3429 "       // gets blackened at edges due to leaving the area that contains actual\n"
3430 "       // content.\n"
3431 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3432 "       // 'appening.\n"
3433 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3439 "#endif\n"
3440 "\n"
3441 "       gl_FragColor = float4(color);\n"
3442 "}\n"
3443 "#endif // FRAGMENT_SHADER\n"
3444 "\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3454 ;
3455
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3459
3460 //=======================================================================================================================================================
3461
3462 typedef struct shaderpermutationinfo_s
3463 {
3464         const char *pretext;
3465         const char *name;
3466 }
3467 shaderpermutationinfo_t;
3468
3469 typedef struct shadermodeinfo_s
3470 {
3471         const char *vertexfilename;
3472         const char *geometryfilename;
3473         const char *fragmentfilename;
3474         const char *pretext;
3475         const char *name;
3476 }
3477 shadermodeinfo_t;
3478
3479 typedef enum shaderpermutation_e
3480 {
3481         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3512 }
3513 shaderpermutation_t;
3514
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3517 {
3518         {"#define USEDIFFUSE\n", " diffuse"},
3519         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520         {"#define USEVIEWTINT\n", " viewtint"},
3521         {"#define USECOLORMAPPING\n", " colormapping"},
3522         {"#define USESATURATION\n", " saturation"},
3523         {"#define USEFOGINSIDE\n", " foginside"},
3524         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526         {"#define USEGAMMARAMPS\n", " gammaramps"},
3527         {"#define USECUBEFILTER\n", " cubefilter"},
3528         {"#define USEGLOW\n", " glow"},
3529         {"#define USEBLOOM\n", " bloom"},
3530         {"#define USESPECULAR\n", " specular"},
3531         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533         {"#define USEREFLECTION\n", " reflection"},
3534         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545         {"#define USEALPHAKILL\n", " alphakill"},
3546         {"#define USEREFLECTCUBE\n", " reflectcube"},
3547 };
3548
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3551 {
3552         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3567         SHADERMODE_COUNT
3568 }
3569 shadermode_t;
3570
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3573 {
3574         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3589 };
3590
3591 #ifdef SUPPORTCG
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3593 {
3594         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3609 };
3610 #endif
3611
3612 #ifdef SUPPORTD3D
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3614 {
3615         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3630 };
3631 #endif
3632
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_glsl_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         int program;
3645         /// locations of detected uniforms in program object, or -1 if not found
3646         int loc_Texture_First;
3647         int loc_Texture_Second;
3648         int loc_Texture_GammaRamps;
3649         int loc_Texture_Normal;
3650         int loc_Texture_Color;
3651         int loc_Texture_Gloss;
3652         int loc_Texture_Glow;
3653         int loc_Texture_SecondaryNormal;
3654         int loc_Texture_SecondaryColor;
3655         int loc_Texture_SecondaryGloss;
3656         int loc_Texture_SecondaryGlow;
3657         int loc_Texture_Pants;
3658         int loc_Texture_Shirt;
3659         int loc_Texture_FogHeightTexture;
3660         int loc_Texture_FogMask;
3661         int loc_Texture_Lightmap;
3662         int loc_Texture_Deluxemap;
3663         int loc_Texture_Attenuation;
3664         int loc_Texture_Cube;
3665         int loc_Texture_Refraction;
3666         int loc_Texture_Reflection;
3667         int loc_Texture_ShadowMapRect;
3668         int loc_Texture_ShadowMapCube;
3669         int loc_Texture_ShadowMap2D;
3670         int loc_Texture_CubeProjection;
3671         int loc_Texture_ScreenDepth;
3672         int loc_Texture_ScreenNormalMap;
3673         int loc_Texture_ScreenDiffuse;
3674         int loc_Texture_ScreenSpecular;
3675         int loc_Texture_ReflectMask;
3676         int loc_Texture_ReflectCube;
3677         int loc_Alpha;
3678         int loc_BloomBlur_Parameters;
3679         int loc_ClientTime;
3680         int loc_Color_Ambient;
3681         int loc_Color_Diffuse;
3682         int loc_Color_Specular;
3683         int loc_Color_Glow;
3684         int loc_Color_Pants;
3685         int loc_Color_Shirt;
3686         int loc_DeferredColor_Ambient;
3687         int loc_DeferredColor_Diffuse;
3688         int loc_DeferredColor_Specular;
3689         int loc_DeferredMod_Diffuse;
3690         int loc_DeferredMod_Specular;
3691         int loc_DistortScaleRefractReflect;
3692         int loc_EyePosition;
3693         int loc_FogColor;
3694         int loc_FogHeightFade;
3695         int loc_FogPlane;
3696         int loc_FogPlaneViewDist;
3697         int loc_FogRangeRecip;
3698         int loc_LightColor;
3699         int loc_LightDir;
3700         int loc_LightPosition;
3701         int loc_OffsetMapping_Scale;
3702         int loc_PixelSize;
3703         int loc_ReflectColor;
3704         int loc_ReflectFactor;
3705         int loc_ReflectOffset;
3706         int loc_RefractColor;
3707         int loc_Saturation;
3708         int loc_ScreenCenterRefractReflect;
3709         int loc_ScreenScaleRefractReflect;
3710         int loc_ScreenToDepth;
3711         int loc_ShadowMap_Parameters;
3712         int loc_ShadowMap_TextureScale;
3713         int loc_SpecularPower;
3714         int loc_UserVec1;
3715         int loc_UserVec2;
3716         int loc_UserVec3;
3717         int loc_UserVec4;
3718         int loc_ViewTintColor;
3719         int loc_ViewToLight;
3720         int loc_ModelToLight;
3721         int loc_TexMatrix;
3722         int loc_BackgroundTexMatrix;
3723         int loc_ModelViewProjectionMatrix;
3724         int loc_ModelViewMatrix;
3725         int loc_PixelToScreenTexCoord;
3726         int loc_ModelToReflectCube;
3727         int loc_ShadowMapMatrix;
3728         int loc_BloomColorSubtract;
3729 }
3730 r_glsl_permutation_t;
3731
3732 #define SHADERPERMUTATION_HASHSIZE 256
3733
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3740
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3742 {
3743         //unsigned int hashdepth = 0;
3744         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745         r_glsl_permutation_t *p;
3746         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3747         {
3748                 if (p->mode == mode && p->permutation == permutation)
3749                 {
3750                         //if (hashdepth > 10)
3751                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3752                         return p;
3753                 }
3754                 //hashdepth++;
3755         }
3756         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3757         p->mode = mode;
3758         p->permutation = permutation;
3759         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760         r_glsl_permutationhash[mode][hashindex] = p;
3761         //if (hashdepth > 10)
3762         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3763         return p;
3764 }
3765
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3767 {
3768         char *shaderstring;
3769         if (!filename || !filename[0])
3770                 return NULL;
3771         if (!strcmp(filename, "glsl/default.glsl"))
3772         {
3773                 if (!glslshaderstring)
3774                 {
3775                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776                         if (glslshaderstring)
3777                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3778                         else
3779                                 glslshaderstring = (char *)builtinshaderstring;
3780                 }
3781                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783                 return shaderstring;
3784         }
3785         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3786         if (shaderstring)
3787         {
3788                 if (printfromdisknotice)
3789                         Con_DPrintf("from disk %s... ", filename);
3790                 return shaderstring;
3791         }
3792         return shaderstring;
3793 }
3794
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3796 {
3797         int i;
3798         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799         int vertstrings_count = 0;
3800         int geomstrings_count = 0;
3801         int fragstrings_count = 0;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         const char *vertstrings_list[32+3];
3804         const char *geomstrings_list[32+3];
3805         const char *fragstrings_list[32+3];
3806         char permutationname[256];
3807
3808         if (p->compiled)
3809                 return;
3810         p->compiled = true;
3811         p->program = 0;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         // compile the shader program
3865         if (vertstrings_count + geomstrings_count + fragstrings_count)
3866                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3867         if (p->program)
3868         {
3869                 CHECKGLERROR
3870                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871                 // look up all the uniform variable names we care about, so we don't
3872                 // have to look them up every time we set them
3873
3874                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3875                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3876                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3879                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3906                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3908                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3911                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3912                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3913                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3921                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3922                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3924                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3927                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3928                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3929                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3931                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3932                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3935                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3936                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3942                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3943                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3944                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3945                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3946                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3948                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3949                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3950                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957                 // initialize the samplers to refer to the texture units we use
3958                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3959                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3960                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3961                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3962                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3963                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3964                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3965                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3969                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3970                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3971                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3973                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3974                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3975                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3976                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3977                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3978                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3979                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3988                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3989                 CHECKGLERROR
3990                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3991         }
3992         else
3993                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3994
3995         // free the strings
3996         if (vertexstring)
3997                 Mem_Free(vertexstring);
3998         if (geometrystring)
3999                 Mem_Free(geometrystring);
4000         if (fragmentstring)
4001                 Mem_Free(fragmentstring);
4002 }
4003
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4005 {
4006         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007         if (r_glsl_permutation != perm)
4008         {
4009                 r_glsl_permutation = perm;
4010                 if (!r_glsl_permutation->program)
4011                 {
4012                         if (!r_glsl_permutation->compiled)
4013                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4014                         if (!r_glsl_permutation->program)
4015                         {
4016                                 // remove features until we find a valid permutation
4017                                 int i;
4018                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4019                                 {
4020                                         // reduce i more quickly whenever it would not remove any bits
4021                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022                                         if (!(permutation & j))
4023                                                 continue;
4024                                         permutation -= j;
4025                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026                                         if (!r_glsl_permutation->compiled)
4027                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4028                                         if (r_glsl_permutation->program)
4029                                                 break;
4030                                 }
4031                                 if (i >= SHADERPERMUTATION_COUNT)
4032                                 {
4033                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035                                         qglUseProgramObjectARB(0);CHECKGLERROR
4036                                         return; // no bit left to clear, entire mode is broken
4037                                 }
4038                         }
4039                 }
4040                 CHECKGLERROR
4041                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4042         }
4043         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4046 }
4047
4048 #ifdef SUPPORTCG
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4052 {
4053         /// hash lookup data
4054         struct r_cg_permutation_s *hashnext;
4055         unsigned int mode;
4056         unsigned int permutation;
4057
4058         /// indicates if we have tried compiling this permutation already
4059         qboolean compiled;
4060         /// 0 if compilation failed
4061         CGprogram vprogram;
4062         CGprogram fprogram;
4063         /// locations of detected parameters in programs, or NULL if not found
4064         CGparameter vp_EyePosition;
4065         CGparameter vp_FogPlane;
4066         CGparameter vp_LightDir;
4067         CGparameter vp_LightPosition;
4068         CGparameter vp_ModelToLight;
4069         CGparameter vp_TexMatrix;
4070         CGparameter vp_BackgroundTexMatrix;
4071         CGparameter vp_ModelViewProjectionMatrix;
4072         CGparameter vp_ModelViewMatrix;
4073         CGparameter vp_ShadowMapMatrix;
4074
4075         CGparameter fp_Texture_First;
4076         CGparameter fp_Texture_Second;
4077         CGparameter fp_Texture_GammaRamps;
4078         CGparameter fp_Texture_Normal;
4079         CGparameter fp_Texture_Color;
4080         CGparameter fp_Texture_Gloss;
4081         CGparameter fp_Texture_Glow;
4082         CGparameter fp_Texture_SecondaryNormal;
4083         CGparameter fp_Texture_SecondaryColor;
4084         CGparameter fp_Texture_SecondaryGloss;
4085         CGparameter fp_Texture_SecondaryGlow;
4086         CGparameter fp_Texture_Pants;
4087         CGparameter fp_Texture_Shirt;
4088         CGparameter fp_Texture_FogHeightTexture;
4089         CGparameter fp_Texture_FogMask;
4090         CGparameter fp_Texture_Lightmap;
4091         CGparameter fp_Texture_Deluxemap;
4092         CGparameter fp_Texture_Attenuation;
4093         CGparameter fp_Texture_Cube;
4094         CGparameter fp_Texture_Refraction;
4095         CGparameter fp_Texture_Reflection;
4096         CGparameter fp_Texture_ShadowMapRect;
4097         CGparameter fp_Texture_ShadowMapCube;
4098         CGparameter fp_Texture_ShadowMap2D;
4099         CGparameter fp_Texture_CubeProjection;
4100         CGparameter fp_Texture_ScreenDepth;
4101         CGparameter fp_Texture_ScreenNormalMap;
4102         CGparameter fp_Texture_ScreenDiffuse;
4103         CGparameter fp_Texture_ScreenSpecular;
4104         CGparameter fp_Texture_ReflectMask;
4105         CGparameter fp_Texture_ReflectCube;
4106         CGparameter fp_Alpha;
4107         CGparameter fp_BloomBlur_Parameters;
4108         CGparameter fp_ClientTime;
4109         CGparameter fp_Color_Ambient;
4110         CGparameter fp_Color_Diffuse;
4111         CGparameter fp_Color_Specular;
4112         CGparameter fp_Color_Glow;
4113         CGparameter fp_Color_Pants;
4114         CGparameter fp_Color_Shirt;
4115         CGparameter fp_DeferredColor_Ambient;
4116         CGparameter fp_DeferredColor_Diffuse;
4117         CGparameter fp_DeferredColor_Specular;
4118         CGparameter fp_DeferredMod_Diffuse;
4119         CGparameter fp_DeferredMod_Specular;
4120         CGparameter fp_DistortScaleRefractReflect;
4121         CGparameter fp_EyePosition;
4122         CGparameter fp_FogColor;
4123         CGparameter fp_FogHeightFade;
4124         CGparameter fp_FogPlane;
4125         CGparameter fp_FogPlaneViewDist;
4126         CGparameter fp_FogRangeRecip;
4127         CGparameter fp_LightColor;
4128         CGparameter fp_LightDir;
4129         CGparameter fp_LightPosition;
4130         CGparameter fp_OffsetMapping_Scale;
4131         CGparameter fp_PixelSize;
4132         CGparameter fp_ReflectColor;
4133         CGparameter fp_ReflectFactor;
4134         CGparameter fp_ReflectOffset;
4135         CGparameter fp_RefractColor;
4136         CGparameter fp_Saturation;
4137         CGparameter fp_ScreenCenterRefractReflect;
4138         CGparameter fp_ScreenScaleRefractReflect;
4139         CGparameter fp_ScreenToDepth;
4140         CGparameter fp_ShadowMap_Parameters;
4141         CGparameter fp_ShadowMap_TextureScale;
4142         CGparameter fp_SpecularPower;
4143         CGparameter fp_UserVec1;
4144         CGparameter fp_UserVec2;
4145         CGparameter fp_UserVec3;
4146         CGparameter fp_UserVec4;
4147         CGparameter fp_ViewTintColor;
4148         CGparameter fp_ViewToLight;
4149         CGparameter fp_PixelToScreenTexCoord;
4150         CGparameter fp_ModelToReflectCube;
4151         CGparameter fp_BloomColorSubtract;
4152 }
4153 r_cg_permutation_t;
4154
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4161
4162 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
4163
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4165 {
4166         //unsigned int hashdepth = 0;
4167         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168         r_cg_permutation_t *p;
4169         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4170         {
4171                 if (p->mode == mode && p->permutation == permutation)
4172                 {
4173                         //if (hashdepth > 10)
4174                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4175                         return p;
4176                 }
4177                 //hashdepth++;
4178         }
4179         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4180         p->mode = mode;
4181         p->permutation = permutation;
4182         p->hashnext = r_cg_permutationhash[mode][hashindex];
4183         r_cg_permutationhash[mode][hashindex] = p;
4184         //if (hashdepth > 10)
4185         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4186         return p;
4187 }
4188
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4190 {
4191         char *shaderstring;
4192         if (!filename || !filename[0])
4193                 return NULL;
4194         if (!strcmp(filename, "cg/default.cg"))
4195         {
4196                 if (!cgshaderstring)
4197                 {
4198                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4199                         if (cgshaderstring)
4200                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4201                         else
4202                                 cgshaderstring = (char *)builtincgshaderstring;
4203                 }
4204                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206                 return shaderstring;
4207         }
4208         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4209         if (shaderstring)
4210         {
4211                 if (printfromdisknotice)
4212                         Con_DPrintf("from disk %s... ", filename);
4213                 return shaderstring;
4214         }
4215         return shaderstring;
4216 }
4217
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4219 {
4220         // TODO: load or create .fp and .vp shader files
4221 }
4222
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4224 {
4225         int i;
4226         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227         int vertstrings_count = 0, vertstring_length = 0;
4228         int geomstrings_count = 0, geomstring_length = 0;
4229         int fragstrings_count = 0, fragstring_length = 0;
4230         char *t;
4231         char *vertexstring, *geometrystring, *fragmentstring;
4232         char *vertstring, *geomstring, *fragstring;
4233         const char *vertstrings_list[32+3];
4234         const char *geomstrings_list[32+3];
4235         const char *fragstrings_list[32+3];
4236         char permutationname[256];
4237         char cachename[256];
4238         CGprofile vertexProfile;
4239         CGprofile fragmentProfile;
4240
4241         if (p->compiled)
4242                 return;
4243         p->compiled = true;
4244         p->vprogram = NULL;
4245         p->fprogram = NULL;
4246
4247         permutationname[0] = 0;
4248         cachename[0] = 0;
4249         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4250         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4252
4253         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254         strlcat(cachename, "cg/", sizeof(cachename));
4255
4256         // the first pretext is which type of shader to compile as
4257         // (later these will all be bound together as a program object)
4258         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4261
4262         // the second pretext is the mode (for example a light source)
4263         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267         strlcat(cachename, modeinfo->name, sizeof(cachename));
4268
4269         // now add all the permutation pretexts
4270         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271         {
4272                 if (permutation & (1<<i))
4273                 {
4274                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4279                 }
4280                 else
4281                 {
4282                         // keep line numbers correct
4283                         vertstrings_list[vertstrings_count++] = "\n";
4284                         geomstrings_list[geomstrings_count++] = "\n";
4285                         fragstrings_list[fragstrings_count++] = "\n";
4286                 }
4287         }
4288
4289         // replace spaces in the cachename with _ characters
4290         for (i = 0;cachename[i];i++)
4291                 if (cachename[i] == ' ')
4292                         cachename[i] = '_';
4293
4294         // now append the shader text itself
4295         vertstrings_list[vertstrings_count++] = vertexstring;
4296         geomstrings_list[geomstrings_count++] = geometrystring;
4297         fragstrings_list[fragstrings_count++] = fragmentstring;
4298
4299         // if any sources were NULL, clear the respective list
4300         if (!vertexstring)
4301                 vertstrings_count = 0;
4302         if (!geometrystring)
4303                 geomstrings_count = 0;
4304         if (!fragmentstring)
4305                 fragstrings_count = 0;
4306
4307         vertstring_length = 0;
4308         for (i = 0;i < vertstrings_count;i++)
4309                 vertstring_length += strlen(vertstrings_list[i]);
4310         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4313
4314         geomstring_length = 0;
4315         for (i = 0;i < geomstrings_count;i++)
4316                 geomstring_length += strlen(geomstrings_list[i]);
4317         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4320
4321         fragstring_length = 0;
4322         for (i = 0;i < fragstrings_count;i++)
4323                 fragstring_length += strlen(fragstrings_list[i]);
4324         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4327
4328         CHECKGLERROR
4329         CHECKCGERROR
4330         //vertexProfile = CG_PROFILE_ARBVP1;
4331         //fragmentProfile = CG_PROFILE_ARBFP1;
4332         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4337         CHECKGLERROR
4338
4339         // try to load the cached shader, or generate one
4340         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4341
4342         // if caching failed, do a dynamic compile for now
4343         CHECKCGERROR
4344         if (vertstring[0] && !p->vprogram)
4345                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4346         CHECKCGERROR
4347         if (fragstring[0] && !p->fprogram)
4348                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4349         CHECKCGERROR
4350
4351         // look up all the uniform variable names we care about, so we don't
4352         // have to look them up every time we set them
4353         if (p->vprogram)
4354         {
4355                 CHECKCGERROR
4356                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4359                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4360                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4361                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4362                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4368                 CHECKCGERROR
4369         }
4370         if (p->fprogram)
4371         {
4372                 CHECKCGERROR
4373                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4376                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4407                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4409                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4422                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4423                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4425                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4428                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4429                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4430                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4432                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4436                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4437                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4444                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4445                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4446                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4447                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4452                 CHECKCGERROR
4453         }
4454
4455         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4457         else
4458                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4459
4460         // free the strings
4461         if (vertstring)
4462                 Mem_Free(vertstring);
4463         if (geomstring)
4464                 Mem_Free(geomstring);
4465         if (fragstring)
4466                 Mem_Free(fragstring);
4467         if (vertexstring)
4468                 Mem_Free(vertexstring);
4469         if (geometrystring)
4470                 Mem_Free(geometrystring);
4471         if (fragmentstring)
4472                 Mem_Free(fragmentstring);
4473 }
4474
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4476 {
4477         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4478         CHECKGLERROR
4479         CHECKCGERROR
4480         if (r_cg_permutation != perm)
4481         {
4482                 r_cg_permutation = perm;
4483                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4484                 {
4485                         if (!r_cg_permutation->compiled)
4486                                 R_CG_CompilePermutation(perm, mode, permutation);
4487                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4488                         {
4489                                 // remove features until we find a valid permutation
4490                                 int i;
4491                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4492                                 {
4493                                         // reduce i more quickly whenever it would not remove any bits
4494                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495                                         if (!(permutation & j))
4496                                                 continue;
4497                                         permutation -= j;
4498                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499                                         if (!r_cg_permutation->compiled)
4500                                                 R_CG_CompilePermutation(perm, mode, permutation);
4501                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4502                                                 break;
4503                                 }
4504                                 if (i >= SHADERPERMUTATION_COUNT)
4505                                 {
4506                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508                                         return; // no bit left to clear, entire mode is broken
4509                                 }
4510                         }
4511                 }
4512                 CHECKGLERROR
4513                 CHECKCGERROR
4514                 if (r_cg_permutation->vprogram)
4515                 {
4516                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4519                 }
4520                 else
4521                 {
4522                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4524                 }
4525                 if (r_cg_permutation->fprogram)
4526                 {
4527                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4530                 }
4531                 else
4532                 {
4533                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4535                 }
4536         }
4537         CHECKCGERROR
4538         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4541 }
4542
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4544 {
4545         cgGLSetTextureParameter(param, R_GetTexture(tex));
4546         cgGLEnableTextureParameter(param);
4547 }
4548 #endif
4549
4550 #ifdef SUPPORTD3D
4551
4552 #ifdef SUPPORTD3D
4553 #include <d3d9.h>
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4556 #endif
4557
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4560 {
4561         /// hash lookup data
4562         struct r_hlsl_permutation_s *hashnext;
4563         unsigned int mode;
4564         unsigned int permutation;
4565
4566         /// indicates if we have tried compiling this permutation already
4567         qboolean compiled;
4568         /// NULL if compilation failed
4569         IDirect3DVertexShader9 *vertexshader;
4570         IDirect3DPixelShader9 *pixelshader;
4571 }
4572 r_hlsl_permutation_t;
4573
4574 typedef enum D3DVSREGISTER_e
4575 {
4576         D3DVSREGISTER_TexMatrix = 0, // float4x4
4577         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581         D3DVSREGISTER_ModelToLight = 20, // float4x4
4582         D3DVSREGISTER_EyePosition = 24,
4583         D3DVSREGISTER_FogPlane = 25,
4584         D3DVSREGISTER_LightDir = 26,
4585         D3DVSREGISTER_LightPosition = 27,
4586 }
4587 D3DVSREGISTER_t;
4588
4589 typedef enum D3DPSREGISTER_e
4590 {
4591         D3DPSREGISTER_Alpha = 0,
4592         D3DPSREGISTER_BloomBlur_Parameters = 1,
4593         D3DPSREGISTER_ClientTime = 2,
4594         D3DPSREGISTER_Color_Ambient = 3,
4595         D3DPSREGISTER_Color_Diffuse = 4,
4596         D3DPSREGISTER_Color_Specular = 5,
4597         D3DPSREGISTER_Color_Glow = 6,
4598         D3DPSREGISTER_Color_Pants = 7,
4599         D3DPSREGISTER_Color_Shirt = 8,
4600         D3DPSREGISTER_DeferredColor_Ambient = 9,
4601         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602         D3DPSREGISTER_DeferredColor_Specular = 11,
4603         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604         D3DPSREGISTER_DeferredMod_Specular = 13,
4605         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606         D3DPSREGISTER_EyePosition = 15, // unused
4607         D3DPSREGISTER_FogColor = 16,
4608         D3DPSREGISTER_FogHeightFade = 17,
4609         D3DPSREGISTER_FogPlane = 18,
4610         D3DPSREGISTER_FogPlaneViewDist = 19,
4611         D3DPSREGISTER_FogRangeRecip = 20,
4612         D3DPSREGISTER_LightColor = 21,
4613         D3DPSREGISTER_LightDir = 22, // unused
4614         D3DPSREGISTER_LightPosition = 23,
4615         D3DPSREGISTER_OffsetMapping_Scale = 24,
4616         D3DPSREGISTER_PixelSize = 25,
4617         D3DPSREGISTER_ReflectColor = 26,
4618         D3DPSREGISTER_ReflectFactor = 27,
4619         D3DPSREGISTER_ReflectOffset = 28,
4620         D3DPSREGISTER_RefractColor = 29,
4621         D3DPSREGISTER_Saturation = 30,
4622         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624         D3DPSREGISTER_ScreenToDepth = 33,
4625         D3DPSREGISTER_ShadowMap_Parameters = 34,
4626         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627         D3DPSREGISTER_SpecularPower = 36,
4628         D3DPSREGISTER_UserVec1 = 37,
4629         D3DPSREGISTER_UserVec2 = 38,
4630         D3DPSREGISTER_UserVec3 = 39,
4631         D3DPSREGISTER_UserVec4 = 40,
4632         D3DPSREGISTER_ViewTintColor = 41,
4633         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634         D3DPSREGISTER_BloomColorSubtract = 43,
4635         D3DPSREGISTER_ViewToLight = 44, // float4x4
4636         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4637         // next at 52
4638 }
4639 D3DPSREGISTER_t;
4640
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4647
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4649 {
4650         //unsigned int hashdepth = 0;
4651         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652         r_hlsl_permutation_t *p;
4653         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4654         {
4655                 if (p->mode == mode && p->permutation == permutation)
4656                 {
4657                         //if (hashdepth > 10)
4658                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4659                         return p;
4660                 }
4661                 //hashdepth++;
4662         }
4663         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4664         p->mode = mode;
4665         p->permutation = permutation;
4666         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667         r_hlsl_permutationhash[mode][hashindex] = p;
4668         //if (hashdepth > 10)
4669         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4670         return p;
4671 }
4672
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4674 {
4675         char *shaderstring;
4676         if (!filename || !filename[0])
4677                 return NULL;
4678         if (!strcmp(filename, "hlsl/default.hlsl"))
4679         {
4680                 if (!hlslshaderstring)
4681                 {
4682                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683                         if (hlslshaderstring)
4684                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4685                         else
4686                                 hlslshaderstring = (char *)builtincgshaderstring;
4687                 }
4688                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690                 return shaderstring;
4691         }
4692         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4693         if (shaderstring)
4694         {
4695                 if (printfromdisknotice)
4696                         Con_DPrintf("from disk %s... ", filename);
4697                 return shaderstring;
4698         }
4699         return shaderstring;
4700 }
4701
4702 #include <d3dx9.h>
4703 //#include <d3dx9shader.h>
4704 //#include <d3dx9mesh.h>
4705
4706 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4707 {
4708         DWORD *vsbin = NULL;
4709         DWORD *psbin = NULL;
4710         fs_offset_t vsbinsize;
4711         fs_offset_t psbinsize;
4712 //      IDirect3DVertexShader9 *vs = NULL;
4713 //      IDirect3DPixelShader9 *ps = NULL;
4714         ID3DXBuffer *vslog = NULL;
4715         ID3DXBuffer *vsbuffer = NULL;
4716         ID3DXConstantTable *vsconstanttable = NULL;
4717         ID3DXBuffer *pslog = NULL;
4718         ID3DXBuffer *psbuffer = NULL;
4719         ID3DXConstantTable *psconstanttable = NULL;
4720         int vsresult = 0;
4721         int psresult = 0;
4722         char temp[MAX_INPUTLINE];
4723         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4724         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4725         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4726         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4727         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4728         if ((!vsbin && vertstring) || (!psbin && fragstring))
4729         {
4730                 const char* dllnames_d3dx9 [] =
4731                 {
4732                         "d3dx9_43.dll",
4733                         "d3dx9_42.dll",
4734                         "d3dx9_41.dll",
4735                         "d3dx9_40.dll",
4736                         "d3dx9_39.dll",
4737                         "d3dx9_38.dll",
4738                         "d3dx9_37.dll",
4739                         "d3dx9_36.dll",
4740                         "d3dx9_35.dll",
4741                         "d3dx9_34.dll",
4742                         "d3dx9_33.dll",
4743                         "d3dx9_32.dll",
4744                         "d3dx9_31.dll",
4745                         "d3dx9_30.dll",
4746                         "d3dx9_29.dll",
4747                         "d3dx9_28.dll",
4748                         "d3dx9_27.dll",
4749                         "d3dx9_26.dll",
4750                         "d3dx9_25.dll",
4751                         "d3dx9_24.dll",
4752                         NULL
4753                 };
4754                 dllhandle_t d3dx9_dll = NULL;
4755                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4756                 dllfunction_t d3dx9_dllfuncs[] =
4757                 {
4758                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4759                         {NULL, NULL}
4760                 };
4761                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4762                 {
4763                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4764                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4765                         if (vertstring && vertstring[0])
4766                         {
4767                                 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, 0, &vsbuffer, &vslog, &vsconstanttable);
4768                                 if (vsbuffer)
4769                                 {
4770                                         vsbinsize = vsbuffer->GetBufferSize();
4771                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4772                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4773                                         vsbuffer->Release();
4774                                 }
4775                                 if (vslog)
4776                                 {
4777                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4778                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4779                                         vslog->Release();
4780                                 }
4781                         }
4782                         if (fragstring && fragstring[0])
4783                         {
4784                                 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, 0, &psbuffer, &pslog, &psconstanttable);
4785                                 if (psbuffer)
4786                                 {
4787                                         psbinsize = psbuffer->GetBufferSize();
4788                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4789                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4790                                         psbuffer->Release();
4791                                 }
4792                                 if (pslog)
4793                                 {
4794                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4795                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4796                                         pslog->Release();
4797                                 }
4798                         }
4799                         Sys_UnloadLibrary(&d3dx9_dll);
4800                 }
4801                 else
4802                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4803         }
4804         if (vsbin)
4805         {
4806                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4807                 if (FAILED(vsresult))
4808                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4809         }
4810         if (psbin)
4811         {
4812                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4813                 if (FAILED(psresult))
4814                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4815         }
4816         // free the shader data
4817         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4818         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4819 }
4820
4821 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4822 {
4823         int i;
4824         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4825         int vertstrings_count = 0, vertstring_length = 0;
4826         int geomstrings_count = 0, geomstring_length = 0;
4827         int fragstrings_count = 0, fragstring_length = 0;
4828         char *t;
4829         char *vertexstring, *geometrystring, *fragmentstring;
4830         char *vertstring, *geomstring, *fragstring;
4831         const char *vertstrings_list[32+3];
4832         const char *geomstrings_list[32+3];
4833         const char *fragstrings_list[32+3];
4834         char permutationname[256];
4835         char cachename[256];
4836
4837         if (p->compiled)
4838                 return;
4839         p->compiled = true;
4840         p->vertexshader = NULL;
4841         p->pixelshader = NULL;
4842
4843         permutationname[0] = 0;
4844         cachename[0] = 0;
4845         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4846         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4847         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4848
4849         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4850         strlcat(cachename, "hlsl/", sizeof(cachename));
4851
4852         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4853         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4854         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4855         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4856
4857         // the first pretext is which type of shader to compile as
4858         // (later these will all be bound together as a program object)
4859         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4860         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4861         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4862
4863         // the second pretext is the mode (for example a light source)
4864         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4865         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4866         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4867         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4868         strlcat(cachename, modeinfo->name, sizeof(cachename));
4869
4870         // now add all the permutation pretexts
4871         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4872         {
4873                 if (permutation & (1<<i))
4874                 {
4875                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4876                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4877                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4878                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4879                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4880                 }
4881                 else
4882                 {
4883                         // keep line numbers correct
4884                         vertstrings_list[vertstrings_count++] = "\n";
4885                         geomstrings_list[geomstrings_count++] = "\n";
4886                         fragstrings_list[fragstrings_count++] = "\n";
4887                 }
4888         }
4889
4890         // replace spaces in the cachename with _ characters
4891         for (i = 0;cachename[i];i++)
4892                 if (cachename[i] == ' ')
4893                         cachename[i] = '_';
4894
4895         // now append the shader text itself
4896         vertstrings_list[vertstrings_count++] = vertexstring;
4897         geomstrings_list[geomstrings_count++] = geometrystring;
4898         fragstrings_list[fragstrings_count++] = fragmentstring;
4899
4900         // if any sources were NULL, clear the respective list
4901         if (!vertexstring)
4902                 vertstrings_count = 0;
4903         if (!geometrystring)
4904                 geomstrings_count = 0;
4905         if (!fragmentstring)
4906                 fragstrings_count = 0;
4907
4908         vertstring_length = 0;
4909         for (i = 0;i < vertstrings_count;i++)
4910                 vertstring_length += strlen(vertstrings_list[i]);
4911         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4912         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4913                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4914
4915         geomstring_length = 0;
4916         for (i = 0;i < geomstrings_count;i++)
4917                 geomstring_length += strlen(geomstrings_list[i]);
4918         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4919         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4920                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4921
4922         fragstring_length = 0;
4923         for (i = 0;i < fragstrings_count;i++)
4924                 fragstring_length += strlen(fragstrings_list[i]);
4925         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4926         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4927                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4928
4929         // try to load the cached shader, or generate one
4930         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4931
4932         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4933                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4934         else
4935                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4936
4937         // free the strings
4938         if (vertstring)
4939                 Mem_Free(vertstring);
4940         if (geomstring)
4941                 Mem_Free(geomstring);
4942         if (fragstring)
4943                 Mem_Free(fragstring);
4944         if (vertexstring)
4945                 Mem_Free(vertexstring);
4946         if (geometrystring)
4947                 Mem_Free(geometrystring);
4948         if (fragmentstring)
4949                 Mem_Free(fragmentstring);
4950 }
4951
4952 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4953 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4954 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4955 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4956 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4957 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4958
4959 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4960 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4961 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4962 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4963 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4964 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4965
4966 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4967 {
4968         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4969         if (r_hlsl_permutation != perm)
4970         {
4971                 r_hlsl_permutation = perm;
4972                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4973                 {
4974                         if (!r_hlsl_permutation->compiled)
4975                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4976                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4977                         {
4978                                 // remove features until we find a valid permutation
4979                                 int i;
4980                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4981                                 {
4982                                         // reduce i more quickly whenever it would not remove any bits
4983                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4984                                         if (!(permutation & j))
4985                                                 continue;
4986                                         permutation -= j;
4987                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4988                                         if (!r_hlsl_permutation->compiled)
4989                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4990                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4991                                                 break;
4992                                 }
4993                                 if (i >= SHADERPERMUTATION_COUNT)
4994                                 {
4995                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4996                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4997                                         return; // no bit left to clear, entire mode is broken
4998                                 }
4999                         }
5000                 }
5001                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5002                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5003         }
5004         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5005         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5006         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5007 }
5008 #endif
5009
5010 void R_GLSL_Restart_f(void)
5011 {
5012         unsigned int i, limit;
5013         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5014                 Mem_Free(glslshaderstring);
5015         glslshaderstring = NULL;
5016         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5017                 Mem_Free(cgshaderstring);
5018         cgshaderstring = NULL;
5019         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5020                 Mem_Free(hlslshaderstring);
5021         hlslshaderstring = NULL;
5022         switch(vid.renderpath)
5023         {
5024         case RENDERPATH_D3D9:
5025 #ifdef SUPPORTD3D
5026                 {
5027                         r_hlsl_permutation_t *p;
5028                         r_hlsl_permutation = NULL;
5029 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5030 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5031 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5032 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5033                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5034                         for (i = 0;i < limit;i++)
5035                         {
5036                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5037                                 {
5038                                         if (p->vertexshader)
5039                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5040                                         if (p->pixelshader)
5041                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5042                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5043                                 }
5044                         }
5045                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5046                 }
5047 #endif
5048                 break;
5049         case RENDERPATH_D3D10:
5050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5051                 break;
5052         case RENDERPATH_D3D11:
5053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5054                 break;
5055         case RENDERPATH_GL20:
5056                 {
5057                         r_glsl_permutation_t *p;
5058                         r_glsl_permutation = NULL;
5059                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5060                         for (i = 0;i < limit;i++)
5061                         {
5062                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5063                                 {
5064                                         GL_Backend_FreeProgram(p->program);
5065                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5066                                 }
5067                         }
5068                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5069                 }
5070                 break;
5071         case RENDERPATH_CGGL:
5072 #ifdef SUPPORTCG
5073                 {
5074                         r_cg_permutation_t *p;
5075                         r_cg_permutation = NULL;
5076                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5077                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5078                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5079                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5080                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5081                         for (i = 0;i < limit;i++)
5082                         {
5083                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5084                                 {
5085                                         if (p->vprogram)
5086                                                 cgDestroyProgram(p->vprogram);
5087                                         if (p->fprogram)
5088                                                 cgDestroyProgram(p->fprogram);
5089                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5090                                 }
5091                         }
5092                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5093                 }
5094 #endif
5095                 break;
5096         case RENDERPATH_GL13:
5097         case RENDERPATH_GL11:
5098                 break;
5099         }
5100 }
5101
5102 void R_GLSL_DumpShader_f(void)
5103 {
5104         int i;
5105         qfile_t *file;
5106
5107         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5108         if (file)
5109         {
5110                 FS_Print(file, "/* The engine may define the following macros:\n");
5111                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5112                 for (i = 0;i < SHADERMODE_COUNT;i++)
5113                         FS_Print(file, glslshadermodeinfo[i].pretext);
5114                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5115                         FS_Print(file, shaderpermutationinfo[i].pretext);
5116                 FS_Print(file, "*/\n");
5117                 FS_Print(file, builtinshaderstring);
5118                 FS_Close(file);
5119                 Con_Printf("glsl/default.glsl written\n");
5120         }
5121         else
5122                 Con_Printf("failed to write to glsl/default.glsl\n");
5123
5124 #ifdef SUPPORTCG
5125         file = FS_OpenRealFile("cg/default.cg", "w", false);
5126         if (file)
5127         {
5128                 FS_Print(file, "/* The engine may define the following macros:\n");
5129                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5130                 for (i = 0;i < SHADERMODE_COUNT;i++)
5131                         FS_Print(file, cgshadermodeinfo[i].pretext);
5132                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5133                         FS_Print(file, shaderpermutationinfo[i].pretext);
5134                 FS_Print(file, "*/\n");
5135                 FS_Print(file, builtincgshaderstring);
5136                 FS_Close(file);
5137                 Con_Printf("cg/default.cg written\n");
5138         }
5139         else
5140                 Con_Printf("failed to write to cg/default.cg\n");
5141 #endif
5142
5143 #ifdef SUPPORTD3D
5144         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5145         if (file)
5146         {
5147                 FS_Print(file, "/* The engine may define the following macros:\n");
5148                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5149                 for (i = 0;i < SHADERMODE_COUNT;i++)
5150                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5151                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5152                         FS_Print(file, shaderpermutationinfo[i].pretext);
5153                 FS_Print(file, "*/\n");
5154                 FS_Print(file, builtincgshaderstring);
5155                 FS_Close(file);
5156                 Con_Printf("hlsl/default.hlsl written\n");
5157         }
5158         else
5159                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5160 #endif
5161 }
5162
5163 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5164 {
5165         if (!second)
5166                 texturemode = GL_MODULATE;
5167         switch (vid.renderpath)
5168         {
5169         case RENDERPATH_D3D9:
5170 #ifdef SUPPORTD3D
5171                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5172                 R_Mesh_TexBind(GL20TU_FIRST , first );
5173                 R_Mesh_TexBind(GL20TU_SECOND, second);
5174 #endif
5175                 break;
5176         case RENDERPATH_D3D10:
5177                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5178                 break;
5179         case RENDERPATH_D3D11:
5180                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5181                 break;
5182         case RENDERPATH_GL20:
5183                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5184                 R_Mesh_TexBind(GL20TU_FIRST , first );
5185                 R_Mesh_TexBind(GL20TU_SECOND, second);
5186                 break;
5187         case RENDERPATH_CGGL:
5188 #ifdef SUPPORTCG
5189                 CHECKCGERROR
5190                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5191                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5192                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5193 #endif
5194                 break;
5195         case RENDERPATH_GL13:
5196                 R_Mesh_TexBind(0, first );
5197                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5198                 R_Mesh_TexBind(1, second);
5199                 if (second)
5200                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5201                 break;
5202         case RENDERPATH_GL11:
5203                 R_Mesh_TexBind(0, first );
5204                 break;
5205         }
5206 }
5207
5208 void R_SetupShader_DepthOrShadow(void)
5209 {
5210         switch (vid.renderpath)
5211         {
5212         case RENDERPATH_D3D9:
5213 #ifdef SUPPORTD3D
5214                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5215 #endif
5216                 break;
5217         case RENDERPATH_D3D10:
5218                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5219                 break;
5220         case RENDERPATH_D3D11:
5221                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5222                 break;
5223         case RENDERPATH_GL20:
5224                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5225                 break;
5226         case RENDERPATH_CGGL:
5227 #ifdef SUPPORTCG
5228                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5229 #endif
5230                 break;
5231         case RENDERPATH_GL13:
5232                 R_Mesh_TexBind(0, 0);
5233                 R_Mesh_TexBind(1, 0);
5234                 break;
5235         case RENDERPATH_GL11:
5236                 R_Mesh_TexBind(0, 0);
5237                 break;
5238         }
5239 }
5240
5241 void R_SetupShader_ShowDepth(void)
5242 {
5243         switch (vid.renderpath)
5244         {
5245         case RENDERPATH_D3D9:
5246 #ifdef SUPPORTHLSL
5247                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5248 #endif
5249                 break;
5250         case RENDERPATH_D3D10:
5251                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5252                 break;
5253         case RENDERPATH_D3D11:
5254                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5255                 break;
5256         case RENDERPATH_GL20:
5257                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5258                 break;
5259         case RENDERPATH_CGGL:
5260 #ifdef SUPPORTCG
5261                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5262 #endif
5263                 break;
5264         case RENDERPATH_GL13:
5265                 break;
5266         case RENDERPATH_GL11:
5267                 break;
5268         }
5269 }
5270
5271 extern qboolean r_shadow_usingdeferredprepass;
5272 extern cvar_t r_shadow_deferred_8bitrange;
5273 extern rtexture_t *r_shadow_attenuationgradienttexture;
5274 extern rtexture_t *r_shadow_attenuation2dtexture;
5275 extern rtexture_t *r_shadow_attenuation3dtexture;
5276 extern qboolean r_shadow_usingshadowmaprect;
5277 extern qboolean r_shadow_usingshadowmapcube;
5278 extern qboolean r_shadow_usingshadowmap2d;
5279 extern qboolean r_shadow_usingshadowmaportho;
5280 extern float r_shadow_shadowmap_texturescale[2];
5281 extern float r_shadow_shadowmap_parameters[4];
5282 extern qboolean r_shadow_shadowmapvsdct;
5283 extern qboolean r_shadow_shadowmapsampler;
5284 extern int r_shadow_shadowmappcf;
5285 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5286 extern rtexture_t *r_shadow_shadowmap2dtexture;
5287 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5288 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5289 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5290 extern matrix4x4_t r_shadow_shadowmapmatrix;
5291 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5292 extern int r_shadow_prepass_width;
5293 extern int r_shadow_prepass_height;
5294 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5295 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5296 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5297 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5298 extern cvar_t gl_mesh_separatearrays;
5299 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5300 {
5301         // a blendfunc allows colormod if:
5302         // a) it can never keep the destination pixel invariant, or
5303         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5304         // this is to prevent unintended side effects from colormod
5305
5306         // in formulas:
5307         // IF there is a (s, sa) for which for all (d, da),
5308         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5309         // THEN, for this (s, sa) and all (colormod, d, da):
5310         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5311         // OBVIOUSLY, this means that
5312         //   s*colormod * src(s*colormod, d, sa, da) = 0
5313         //   dst(s*colormod, d, sa, da)              = 1
5314
5315         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5316
5317         // main condition to leave dst color invariant:
5318         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5319         //   src == GL_ZERO:
5320         //     s * 0 + d * dst(s, d, sa, da) == d
5321         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5322         //       => colormod is a problem for GL_SRC_COLOR only
5323         //   src == GL_ONE:
5324         //     s + d * dst(s, d, sa, da) == d
5325         //       => s == 0
5326         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5327         //       => colormod is never problematic for these
5328         //   src == GL_SRC_COLOR:
5329         //     s*s + d * dst(s, d, sa, da) == d
5330         //       => s == 0
5331         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5332         //       => colormod is never problematic for these
5333         //   src == GL_ONE_MINUS_SRC_COLOR:
5334         //     s*(1-s) + d * dst(s, d, sa, da) == d
5335         //       => s == 0 or s == 1
5336         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5337         //       => colormod is a problem for GL_SRC_COLOR only
5338         //   src == GL_DST_COLOR
5339         //     s*d + d * dst(s, d, sa, da) == d
5340         //       => s == 1
5341         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5342         //       => colormod is always a problem
5343         //     or
5344         //       => s == 0
5345         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5346         //       => colormod is never problematic for these
5347         //       => BUT, we do not know s! We must assume it is problematic
5348         //       then... except in GL_ONE case, where we know all invariant
5349         //       cases are fine
5350         //   src == GL_ONE_MINUS_DST_COLOR
5351         //     s*(1-d) + d * dst(s, d, sa, da) == d
5352         //       => s == 0 (1-d is impossible to handle for our desired result)
5353         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5354         //       => colormod is never problematic for these
5355         //   src == GL_SRC_ALPHA
5356         //     s*sa + d * dst(s, d, sa, da) == d
5357         //       => s == 0, or sa == 0
5358         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5359         //       => colormod breaks in the case GL_SRC_COLOR only
5360         //   src == GL_ONE_MINUS_SRC_ALPHA
5361         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5362         //       => s == 0, or sa == 1
5363         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5364         //       => colormod breaks in the case GL_SRC_COLOR only
5365         //   src == GL_DST_ALPHA
5366         //     s*da + d * dst(s, d, sa, da) == d
5367         //       => s == 0
5368         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5369         //       => colormod is never problematic for these
5370
5371         switch(src)
5372         {
5373                 case GL_ZERO:
5374                 case GL_ONE_MINUS_SRC_COLOR:
5375                 case GL_SRC_ALPHA:
5376                 case GL_ONE_MINUS_SRC_ALPHA:
5377                         if(dst == GL_SRC_COLOR)
5378                                 return false;
5379                         return true;
5380                 case GL_ONE:
5381                 case GL_SRC_COLOR:
5382                 case GL_ONE_MINUS_DST_COLOR:
5383                 case GL_DST_ALPHA:
5384                 case GL_ONE_MINUS_DST_ALPHA:
5385                         return true;
5386                 case GL_DST_COLOR:
5387                         if(dst == GL_ONE)
5388                                 return true;
5389                         return false;
5390                 default:
5391                         return false;
5392         }
5393 }
5394 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5395 {
5396         // select a permutation of the lighting shader appropriate to this
5397         // combination of texture, entity, light source, and fogging, only use the
5398         // minimum features necessary to avoid wasting rendering time in the
5399         // fragment shader on features that are not being used
5400         unsigned int permutation = 0;
5401         unsigned int mode = 0;
5402         qboolean allow_colormod;
5403         static float dummy_colormod[3] = {1, 1, 1};
5404         float *colormod = rsurface.colormod;
5405         float m16f[16];
5406         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5407         if (rsurfacepass == RSURFPASS_BACKGROUND)
5408         {
5409                 // distorted background
5410                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5411                         mode = SHADERMODE_WATER;
5412                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5413                         mode = SHADERMODE_REFRACTION;
5414                 else
5415                 {
5416                         mode = SHADERMODE_GENERIC;
5417                         permutation |= SHADERPERMUTATION_DIFFUSE;
5418                 }
5419                 GL_AlphaTest(false);
5420                 GL_BlendFunc(GL_ONE, GL_ZERO);
5421                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5422         }
5423         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5424         {
5425                 if (r_glsl_offsetmapping.integer)
5426                 {
5427                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5428                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5429                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5430                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5431                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5432                         {
5433                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5434                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5435                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5436                         }
5437                 }
5438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5439                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5441                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5442                 // normalmap (deferred prepass), may use alpha test on diffuse
5443                 mode = SHADERMODE_DEFERREDGEOMETRY;
5444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5446                 GL_AlphaTest(false);
5447                 GL_BlendFunc(GL_ONE, GL_ZERO);
5448                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5449         }
5450         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5451         {
5452                 if (r_glsl_offsetmapping.integer)
5453                 {
5454                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5455                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5456                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5457                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5458                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5459                         {
5460                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5461                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5462                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5463                         }
5464                 }
5465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5466                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5467                 // light source
5468                 mode = SHADERMODE_LIGHTSOURCE;
5469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5470                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5471                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5472                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5473                 if (diffusescale > 0)
5474                         permutation |= SHADERPERMUTATION_DIFFUSE;
5475                 if (specularscale > 0)
5476                 {
5477                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5478                         if (r_shadow_glossexact.integer)
5479                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5480                 }
5481                 if (r_refdef.fogenabled)
5482                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5483                 if (rsurface.texture->colormapping)
5484                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5485                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5486                 {
5487                         if (r_shadow_usingshadowmaprect)
5488                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5489                         if (r_shadow_usingshadowmap2d)
5490                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5491                         if (r_shadow_usingshadowmapcube)
5492                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5493                         else if(r_shadow_shadowmapvsdct)
5494                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5495
5496                         if (r_shadow_shadowmapsampler)
5497                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5498                         if (r_shadow_shadowmappcf > 1)
5499                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5500                         else if (r_shadow_shadowmappcf)
5501                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5502                 }
5503                 if (rsurface.texture->reflectmasktexture)
5504                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5505                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5506                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5507                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5508         }
5509         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5510         {
5511                 if (r_glsl_offsetmapping.integer)
5512                 {
5513                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5514                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5515                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5516                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5517                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5518                         {
5519                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5520                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5521                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5522                         }
5523                 }
5524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5525                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5526                 // unshaded geometry (fullbright or ambient model lighting)
5527                 mode = SHADERMODE_FLATCOLOR;
5528                 ambientscale = diffusescale = specularscale = 0;
5529                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530                         permutation |= SHADERPERMUTATION_GLOW;
5531                 if (r_refdef.fogenabled)
5532                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5533                 if (rsurface.texture->colormapping)
5534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5535                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5536                 {
5537                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5538                         if (r_shadow_usingshadowmaprect)
5539                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5540                         if (r_shadow_usingshadowmap2d)
5541                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5542
5543                         if (r_shadow_shadowmapsampler)
5544                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545                         if (r_shadow_shadowmappcf > 1)
5546                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547                         else if (r_shadow_shadowmappcf)
5548                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551                         permutation |= SHADERPERMUTATION_REFLECTION;
5552                 if (rsurface.texture->reflectmasktexture)
5553                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5554                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5555                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5556                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5557         }
5558         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5559         {
5560                 if (r_glsl_offsetmapping.integer)
5561                 {
5562                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5563                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5564                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5566                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5567                         {
5568                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5569                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5570                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5571                         }
5572                 }
5573                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5574                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5575                 // directional model lighting
5576                 mode = SHADERMODE_LIGHTDIRECTION;
5577                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5578                         permutation |= SHADERPERMUTATION_GLOW;
5579                 permutation |= SHADERPERMUTATION_DIFFUSE;
5580                 if (specularscale > 0)
5581                 {
5582                         permutation |= SHADERPERMUTATION_SPECULAR;
5583                         if (r_shadow_glossexact.integer)
5584                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5585                 }
5586                 if (r_refdef.fogenabled)
5587                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5588                 if (rsurface.texture->colormapping)
5589                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5590                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5591                 {
5592                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5593                         if (r_shadow_usingshadowmaprect)
5594                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5595                         if (r_shadow_usingshadowmap2d)
5596                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5597
5598                         if (r_shadow_shadowmapsampler)
5599                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5600                         if (r_shadow_shadowmappcf > 1)
5601                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5602                         else if (r_shadow_shadowmappcf)
5603                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5604                 }
5605                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5606                         permutation |= SHADERPERMUTATION_REFLECTION;
5607                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5608                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5609                 if (rsurface.texture->reflectmasktexture)
5610                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5611                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5612                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5613                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5614         }
5615         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5616         {
5617                 if (r_glsl_offsetmapping.integer)
5618                 {
5619                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5620                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5621                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5622                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5623                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5624                         {
5625                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5626                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5627                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5628                         }
5629                 }
5630                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5631                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5632                 // ambient model lighting
5633                 mode = SHADERMODE_LIGHTDIRECTION;
5634                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5635                         permutation |= SHADERPERMUTATION_GLOW;
5636                 if (r_refdef.fogenabled)
5637                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5638                 if (rsurface.texture->colormapping)
5639                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5640                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5641                 {
5642                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5643                         if (r_shadow_usingshadowmaprect)
5644                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5645                         if (r_shadow_usingshadowmap2d)
5646                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5647
5648                         if (r_shadow_shadowmapsampler)
5649                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5650                         if (r_shadow_shadowmappcf > 1)
5651                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5652                         else if (r_shadow_shadowmappcf)
5653                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5654                 }
5655                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5656                         permutation |= SHADERPERMUTATION_REFLECTION;
5657                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5658                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5659                 if (rsurface.texture->reflectmasktexture)
5660                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5661                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5662                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5663                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5664         }
5665         else
5666         {
5667                 if (r_glsl_offsetmapping.integer)
5668                 {
5669                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5670                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5671                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5672                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5673                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5674                         {
5675                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5676                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5677                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5678                         }
5679                 }
5680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5682                 // lightmapped wall
5683                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5684                         permutation |= SHADERPERMUTATION_GLOW;
5685                 if (r_refdef.fogenabled)
5686                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5687                 if (rsurface.texture->colormapping)
5688                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5689                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5690                 {
5691                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5692                         if (r_shadow_usingshadowmaprect)
5693                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5694                         if (r_shadow_usingshadowmap2d)
5695                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5696
5697                         if (r_shadow_shadowmapsampler)
5698                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5699                         if (r_shadow_shadowmappcf > 1)
5700                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5701                         else if (r_shadow_shadowmappcf)
5702                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5703                 }
5704                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5705                         permutation |= SHADERPERMUTATION_REFLECTION;
5706                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5707                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5708                 if (rsurface.texture->reflectmasktexture)
5709                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5710                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5711                 {
5712                         // deluxemapping (light direction texture)
5713                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5714                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5715                         else
5716                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5717                         permutation |= SHADERPERMUTATION_DIFFUSE;
5718                         if (specularscale > 0)
5719                         {
5720                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5721                                 if (r_shadow_glossexact.integer)
5722                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5723                         }
5724                 }
5725                 else if (r_glsl_deluxemapping.integer >= 2)
5726                 {
5727                         // fake deluxemapping (uniform light direction in tangentspace)
5728                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5729                         permutation |= SHADERPERMUTATION_DIFFUSE;
5730                         if (specularscale > 0)
5731                         {
5732                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5733                                 if (r_shadow_glossexact.integer)
5734                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5735                         }
5736                 }
5737                 else if (rsurface.uselightmaptexture)
5738                 {
5739                         // ordinary lightmapping (q1bsp, q3bsp)
5740                         mode = SHADERMODE_LIGHTMAP;
5741                 }
5742                 else
5743                 {
5744                         // ordinary vertex coloring (q3bsp)
5745                         mode = SHADERMODE_VERTEXCOLOR;
5746                 }
5747                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5748                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5749                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5750         }
5751         if(!allow_colormod)
5752                 colormod = dummy_colormod;
5753         switch(vid.renderpath)
5754         {
5755         case RENDERPATH_D3D9:
5756 #ifdef SUPPORTD3D
5757                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5758                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5759                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5760                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5761                 if (mode == SHADERMODE_LIGHTSOURCE)
5762                 {
5763                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5764                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5765                 }
5766                 else
5767                 {
5768                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5769                         {
5770                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5771                         }
5772                 }
5773                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5774                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5775                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5776                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5777                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5778
5779                 if (mode == SHADERMODE_LIGHTSOURCE)
5780                 {
5781                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5782                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5783                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5784                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5785                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5786
5787                         // additive passes are only darkened by fog, not tinted
5788                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5790                 }
5791                 else
5792                 {
5793                         if (mode == SHADERMODE_FLATCOLOR)
5794                         {
5795                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5796                         }
5797                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5798                         {
5799                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5800                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5801                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5802                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5803                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5804                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5805                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5806                         }
5807                         else
5808                         {
5809                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5810                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5811                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5812                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5813                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5814                         }
5815                         // additive passes are only darkened by fog, not tinted
5816                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5817                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5818                         else
5819                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5820                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5821                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5822                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5823                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5824                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5825                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5826                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5827                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5828                 }
5829                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5830                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5831                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5832                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5833                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5834                 if (rsurface.texture->pantstexture)
5835                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5836                 else
5837                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5838                 if (rsurface.texture->shirttexture)
5839                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5840                 else
5841                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5842                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5843                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5844                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5845                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5846                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5847                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5848                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5849
5850                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5851                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5852                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5853                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5854                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5855                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5856                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5857                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5858                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5859                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5860                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5861                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5862                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5863                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5864                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5865                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5866                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5867                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5868                 {
5869                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5870                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5871                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5872                 }
5873                 else
5874                 {
5875                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5876                 }
5877 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5878 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5879                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5880                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5881                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5882                 {
5883                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5884                         if (rsurface.rtlight)
5885                         {
5886                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5887                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5888                         }
5889                 }
5890 #endif
5891                 break;
5892         case RENDERPATH_D3D10:
5893                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5894                 break;
5895         case RENDERPATH_D3D11:
5896                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5897                 break;
5898         case RENDERPATH_GL20:
5899                 if (gl_mesh_separatearrays.integer)
5900                 {
5901                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5902                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5903                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5904                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5905                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5906                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5907                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5908                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5909                 }
5910                 else
5911                 {
5912                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5913                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5914                 }
5915                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5916                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5917                 if (mode == SHADERMODE_LIGHTSOURCE)
5918                 {
5919                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5920                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5921                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5922                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5923                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5924                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5925         
5926                         // additive passes are only darkened by fog, not tinted
5927                         if (r_glsl_permutation->loc_FogColor >= 0)
5928                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5929                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5930                 }
5931                 else
5932                 {
5933                         if (mode == SHADERMODE_FLATCOLOR)
5934                         {
5935                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5936                         }
5937                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5938                         {
5939                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5940                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5941                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5942                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5943                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5944                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5945                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5946                         }
5947                         else
5948                         {
5949                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5950                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5951                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5952                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5953                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5954                         }
5955                         // additive passes are only darkened by fog, not tinted
5956                         if (r_glsl_permutation->loc_FogColor >= 0)
5957                         {
5958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5959                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5960                                 else
5961                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5962                         }
5963                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5964                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5965                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5966                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5967                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5968                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5969                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5970                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5971                 }
5972                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5973                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5974                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5975                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5976                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5977
5978                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5979                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5980                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5981                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5982                 {
5983                         if (rsurface.texture->pantstexture)
5984                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5985                         else
5986                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5987                 }
5988                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5989                 {
5990                         if (rsurface.texture->shirttexture)
5991                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5992                         else
5993                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5994                 }
5995                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5996                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5997                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5998                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5999                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6000                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6001                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6002
6003         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6004         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6005         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6006                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6007                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6008                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6009                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6010                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6011                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6012                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6013                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6014                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6015                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6016                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6017                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6018                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6019                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6020                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6021                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6022                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6023                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6024                 {
6025                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6026                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6027                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6028                 }
6029                 else
6030                 {
6031                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6032                 }
6033 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6034 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6035                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6036                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6037                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6038                 {
6039                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6040                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
6041                         if (rsurface.rtlight)
6042                         {
6043                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6044                                 if (r_shadow_usingshadowmapcube)
6045                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6046                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6047                         }
6048                 }
6049                 CHECKGLERROR
6050                 break;
6051         case RENDERPATH_CGGL:
6052 #ifdef SUPPORTCG
6053                 if (gl_mesh_separatearrays.integer)
6054                 {
6055                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6056                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6057                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6058                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6059                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6060                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6061                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6062                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6063                 }
6064                 else
6065                 {
6066                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6067                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6068                 }
6069                 R_SetupShader_SetPermutationCG(mode, permutation);
6070                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6071                 if (mode == SHADERMODE_LIGHTSOURCE)
6072                 {
6073                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6074                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6075                 }
6076                 else
6077                 {
6078                         if (mode == SHADERMODE_LIGHTDIRECTION)
6079                         {
6080                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6081                         }
6082                 }
6083                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6084                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6085                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6086                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6087                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6088                 CHECKGLERROR
6089
6090                 if (mode == SHADERMODE_LIGHTSOURCE)
6091                 {
6092                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6093                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6094                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6095                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6096                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
6097
6098                         // additive passes are only darkened by fog, not tinted
6099                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6100                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6101                 }
6102                 else
6103                 {
6104                         if (mode == SHADERMODE_FLATCOLOR)
6105                         {
6106                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6107                         }
6108                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6109                         {
6110                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6111                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6112                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6113                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6114                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6115                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
6116                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
6117                         }
6118                         else
6119                         {
6120                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6121                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
6122                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
6123                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6124                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6125                         }
6126                         // additive passes are only darkened by fog, not tinted
6127                         if (r_cg_permutation->fp_FogColor)
6128                         {
6129                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6130                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6131                                 else
6132                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6133                                 CHECKCGERROR
6134                         }
6135                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);CHECKCGERROR
6136                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
6137                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
6138                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6139                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6140                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6141                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6142                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6143                 }
6144                 if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6145                 if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6146                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6148                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6149                 if (r_cg_permutation->fp_Color_Pants)
6150                 {
6151                         if (rsurface.texture->pantstexture)
6152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6153                         else
6154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6155                         CHECKCGERROR
6156                 }
6157                 if (r_cg_permutation->fp_Color_Shirt)
6158                 {
6159                         if (rsurface.texture->shirttexture)
6160                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6161                         else
6162                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6163                         CHECKCGERROR
6164                 }
6165                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
6166                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6167                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6168                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6169                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6170                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6171                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6172
6173         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6174         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6175         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6176                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6177                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6178                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6179                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6180                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6181                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6182                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6183                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6184                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6185                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6186                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6187                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
6188                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6189                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6190                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6191                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6192                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6193                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6194                 {
6195                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6196                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6197                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6198                 }
6199                 else
6200                 {
6201                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6202                 }
6203                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6204                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6205                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6206                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6207                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6208                 {
6209                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6210                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6211                         if (rsurface.rtlight)
6212                         {
6213                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6214                                 if (r_shadow_usingshadowmapcube)
6215                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6216                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6217                         }
6218                 }
6219
6220                 CHECKGLERROR
6221 #endif
6222                 break;
6223         case RENDERPATH_GL13:
6224         case RENDERPATH_GL11:
6225                 break;
6226         }
6227 }
6228
6229 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6230 {
6231         // select a permutation of the lighting shader appropriate to this
6232         // combination of texture, entity, light source, and fogging, only use the
6233         // minimum features necessary to avoid wasting rendering time in the
6234         // fragment shader on features that are not being used
6235         unsigned int permutation = 0;
6236         unsigned int mode = 0;
6237         const float *lightcolorbase = rtlight->currentcolor;
6238         float ambientscale = rtlight->ambientscale;
6239         float diffusescale = rtlight->diffusescale;
6240         float specularscale = rtlight->specularscale;
6241         // this is the location of the light in view space
6242         vec3_t viewlightorigin;
6243         // this transforms from view space (camera) to light space (cubemap)
6244         matrix4x4_t viewtolight;
6245         matrix4x4_t lighttoview;
6246         float viewtolight16f[16];
6247         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6248         // light source
6249         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6250         if (rtlight->currentcubemap != r_texture_whitecube)
6251                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6252         if (diffusescale > 0)
6253                 permutation |= SHADERPERMUTATION_DIFFUSE;
6254         if (specularscale > 0)
6255         {
6256                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6257                 if (r_shadow_glossexact.integer)
6258                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6259         }
6260         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6261         {
6262                 if (r_shadow_usingshadowmaprect)
6263                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6264                 if (r_shadow_usingshadowmap2d)
6265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6266                 if (r_shadow_usingshadowmapcube)
6267                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6268                 else if(r_shadow_shadowmapvsdct)
6269                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6270
6271                 if (r_shadow_shadowmapsampler)
6272                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6273                 if (r_shadow_shadowmappcf > 1)
6274                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6275                 else if (r_shadow_shadowmappcf)
6276                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6277         }
6278         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6279         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6280         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6281         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6282         switch(vid.renderpath)
6283         {
6284         case RENDERPATH_D3D9:
6285 #ifdef SUPPORTD3D
6286                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6287                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6288                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6289                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6290                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6291                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6292                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6293                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6294                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6295                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6296                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6297
6298                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6299                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6300                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6301                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6302                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6303                 if (r_shadow_usingshadowmapcube)
6304                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6305                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6306                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6307 #endif
6308                 break;
6309         case RENDERPATH_D3D10:
6310                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6311                 break;
6312         case RENDERPATH_D3D11:
6313                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6314                 break;
6315         case RENDERPATH_GL20:
6316                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6317                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6318                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6319                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6320                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6321                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6322                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6323                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6324                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6325                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6326                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6327
6328                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6329                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6330                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6331                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6332                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6333                 if (r_shadow_usingshadowmapcube)
6334                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6335                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6336                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6337                 break;
6338         case RENDERPATH_CGGL:
6339 #ifdef SUPPORTCG
6340                 R_SetupShader_SetPermutationCG(mode, permutation);
6341                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6342                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6343                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
6344                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
6345                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
6346                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
6347                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
6348                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6349                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
6350                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6351
6352                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6353                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6354                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6355                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6356                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6357                 if (r_shadow_usingshadowmapcube)
6358                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6359                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6360                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6361 #endif
6362                 break;
6363         case RENDERPATH_GL13:
6364         case RENDERPATH_GL11:
6365                 break;
6366         }
6367 }
6368
6369 #define SKINFRAME_HASH 1024
6370
6371 typedef struct
6372 {
6373         int loadsequence; // incremented each level change
6374         memexpandablearray_t array;
6375         skinframe_t *hash[SKINFRAME_HASH];
6376 }
6377 r_skinframe_t;
6378 r_skinframe_t r_skinframe;
6379
6380 void R_SkinFrame_PrepareForPurge(void)
6381 {
6382         r_skinframe.loadsequence++;
6383         // wrap it without hitting zero
6384         if (r_skinframe.loadsequence >= 200)
6385                 r_skinframe.loadsequence = 1;
6386 }
6387
6388 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6389 {
6390         if (!skinframe)
6391                 return;
6392         // mark the skinframe as used for the purging code
6393         skinframe->loadsequence = r_skinframe.loadsequence;
6394 }
6395
6396 void R_SkinFrame_Purge(void)
6397 {
6398         int i;
6399         skinframe_t *s;
6400         for (i = 0;i < SKINFRAME_HASH;i++)
6401         {
6402                 for (s = r_skinframe.hash[i];s;s = s->next)
6403                 {
6404                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6405                         {
6406                                 if (s->merged == s->base)
6407                                         s->merged = NULL;
6408                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6409                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6410                                 R_PurgeTexture(s->merged);s->merged = NULL;
6411                                 R_PurgeTexture(s->base  );s->base   = NULL;
6412                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6413                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6414                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6415                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6416                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6417                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6418                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6419                                 s->loadsequence = 0;
6420                         }
6421                 }
6422         }
6423 }
6424
6425 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6426         skinframe_t *item;
6427         char basename[MAX_QPATH];
6428
6429         Image_StripImageExtension(name, basename, sizeof(basename));
6430
6431         if( last == NULL ) {
6432                 int hashindex;
6433                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6434                 item = r_skinframe.hash[hashindex];
6435         } else {
6436                 item = last->next;
6437         }
6438
6439         // linearly search through the hash bucket
6440         for( ; item ; item = item->next ) {
6441                 if( !strcmp( item->basename, basename ) ) {
6442                         return item;
6443                 }
6444         }
6445         return NULL;
6446 }
6447
6448 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6449 {
6450         skinframe_t *item;
6451         int hashindex;
6452         char basename[MAX_QPATH];
6453
6454         Image_StripImageExtension(name, basename, sizeof(basename));
6455
6456         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6457         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6458                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6459                         break;
6460
6461         if (!item) {
6462                 rtexture_t *dyntexture;
6463                 // check whether its a dynamic texture
6464                 dyntexture = CL_GetDynTexture( basename );
6465                 if (!add && !dyntexture)
6466                         return NULL;
6467                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6468                 memset(item, 0, sizeof(*item));
6469                 strlcpy(item->basename, basename, sizeof(item->basename));
6470                 item->base = dyntexture; // either NULL or dyntexture handle
6471                 item->textureflags = textureflags;
6472                 item->comparewidth = comparewidth;
6473                 item->compareheight = compareheight;
6474                 item->comparecrc = comparecrc;
6475                 item->next = r_skinframe.hash[hashindex];
6476                 r_skinframe.hash[hashindex] = item;
6477         }
6478         else if( item->base == NULL )
6479         {
6480                 rtexture_t *dyntexture;
6481                 // check whether its a dynamic texture
6482                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
6483                 dyntexture = CL_GetDynTexture( basename );
6484                 item->base = dyntexture; // either NULL or dyntexture handle
6485         }
6486
6487         R_SkinFrame_MarkUsed(item);
6488         return item;
6489 }
6490
6491 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6492         { \
6493                 unsigned long long avgcolor[5], wsum; \
6494                 int pix, comp, w; \
6495                 avgcolor[0] = 0; \
6496                 avgcolor[1] = 0; \
6497                 avgcolor[2] = 0; \
6498                 avgcolor[3] = 0; \
6499                 avgcolor[4] = 0; \
6500                 wsum = 0; \
6501                 for(pix = 0; pix < cnt; ++pix) \
6502                 { \
6503                         w = 0; \
6504                         for(comp = 0; comp < 3; ++comp) \
6505                                 w += getpixel; \
6506                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6507                         { \
6508                                 ++wsum; \
6509                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6510                                 w = getpixel; \
6511                                 for(comp = 0; comp < 3; ++comp) \
6512                                         avgcolor[comp] += getpixel * w; \
6513                                 avgcolor[3] += w; \
6514                         } \
6515                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6516                         avgcolor[4] += getpixel; \
6517                 } \
6518                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6519                         avgcolor[3] = 1; \
6520                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6521                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6522                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6523                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6524         }
6525
6526 extern cvar_t gl_picmip;
6527 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6528 {
6529         int j;
6530         unsigned char *pixels;
6531         unsigned char *bumppixels;
6532         unsigned char *basepixels = NULL;
6533         int basepixels_width = 0;
6534         int basepixels_height = 0;
6535         skinframe_t *skinframe;
6536         rtexture_t *ddsbase = NULL;
6537         qboolean ddshasalpha = false;
6538         float ddsavgcolor[4];
6539         char basename[MAX_QPATH];
6540         int miplevel = R_PicmipForFlags(textureflags);
6541         int savemiplevel = miplevel;
6542         int mymiplevel;
6543
6544         if (cls.state == ca_dedicated)
6545                 return NULL;
6546
6547         // return an existing skinframe if already loaded
6548         // if loading of the first image fails, don't make a new skinframe as it
6549         // would cause all future lookups of this to be missing
6550         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6551         if (skinframe && skinframe->base)
6552                 return skinframe;
6553
6554         Image_StripImageExtension(name, basename, sizeof(basename));
6555
6556         // check for DDS texture file first
6557         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6558         {
6559                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6560                 if (basepixels == NULL)
6561                         return NULL;
6562         }
6563
6564         // FIXME handle miplevel
6565
6566         if (developer_loading.integer)
6567                 Con_Printf("loading skin \"%s\"\n", name);
6568
6569         // we've got some pixels to store, so really allocate this new texture now
6570         if (!skinframe)
6571                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6572         skinframe->stain = NULL;
6573         skinframe->merged = NULL;
6574         skinframe->base = NULL;
6575         skinframe->pants = NULL;
6576         skinframe->shirt = NULL;
6577         skinframe->nmap = NULL;
6578         skinframe->gloss = NULL;
6579         skinframe->glow = NULL;
6580         skinframe->fog = NULL;
6581         skinframe->reflect = NULL;
6582         skinframe->hasalpha = false;
6583
6584         if (ddsbase)
6585         {
6586                 skinframe->base = ddsbase;
6587                 skinframe->hasalpha = ddshasalpha;
6588                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6589                 if (r_loadfog && skinframe->hasalpha)
6590                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6591                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6592         }
6593         else
6594         {
6595                 basepixels_width = image_width;
6596                 basepixels_height = image_height;
6597                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6598                 if (textureflags & TEXF_ALPHA)
6599                 {
6600                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6601                         {
6602                                 if (basepixels[j] < 255)
6603                                 {
6604                                         skinframe->hasalpha = true;
6605                                         break;
6606                                 }
6607                         }
6608                         if (r_loadfog && skinframe->hasalpha)
6609                         {
6610                                 // has transparent pixels
6611                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6612                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6613                                 {
6614                                         pixels[j+0] = 255;
6615                                         pixels[j+1] = 255;
6616                                         pixels[j+2] = 255;
6617                                         pixels[j+3] = basepixels[j+3];
6618                                 }
6619                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6620                                 Mem_Free(pixels);
6621                         }
6622                 }
6623                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6624                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6625                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6626                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6627                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6628                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6629         }
6630
6631         if (r_loaddds)
6632         {
6633                 mymiplevel = savemiplevel;
6634                 if (r_loadnormalmap)
6635                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6636                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6637                 if (r_loadgloss)
6638                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6639                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6640                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6641                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6642         }
6643
6644         // _norm is the name used by tenebrae and has been adopted as standard
6645         if (r_loadnormalmap && skinframe->nmap == NULL)
6646         {
6647                 mymiplevel = savemiplevel;
6648                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6649                 {
6650                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6651                         Mem_Free(pixels);
6652                         pixels = NULL;
6653                 }
6654                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6655                 {
6656                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6657                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6658                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6659                         Mem_Free(pixels);
6660                         Mem_Free(bumppixels);
6661                 }
6662                 else if (r_shadow_bumpscale_basetexture.value > 0)
6663                 {
6664                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6665                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6666                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6667                         Mem_Free(pixels);
6668                 }
6669                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6670                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6671         }
6672
6673         // _luma is supported only for tenebrae compatibility
6674         // _glow is the preferred name
6675         mymiplevel = savemiplevel;
6676         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6677         {
6678                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6679                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6680                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6681                 Mem_Free(pixels);pixels = NULL;
6682         }
6683
6684         mymiplevel = savemiplevel;
6685         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6686         {
6687                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6688                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6689                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6690                 Mem_Free(pixels);
6691                 pixels = NULL;
6692         }
6693
6694         mymiplevel = savemiplevel;
6695         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6696         {
6697                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6698                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6699                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6700                 Mem_Free(pixels);
6701                 pixels = NULL;
6702         }
6703
6704         mymiplevel = savemiplevel;
6705         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6706         {
6707                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6708                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6709                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6710                 Mem_Free(pixels);
6711                 pixels = NULL;
6712         }
6713
6714         mymiplevel = savemiplevel;
6715         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6716         {
6717                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6718                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6719                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6720                 Mem_Free(pixels);
6721                 pixels = NULL;
6722         }
6723
6724         if (basepixels)
6725                 Mem_Free(basepixels);
6726
6727         return skinframe;
6728 }
6729
6730 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6731 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6732 {
6733         int i;
6734         unsigned char *temp1, *temp2;
6735         skinframe_t *skinframe;
6736
6737         if (cls.state == ca_dedicated)
6738                 return NULL;
6739
6740         // if already loaded just return it, otherwise make a new skinframe
6741         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6742         if (skinframe && skinframe->base)
6743                 return skinframe;
6744
6745         skinframe->stain = NULL;
6746         skinframe->merged = NULL;
6747         skinframe->base = NULL;
6748         skinframe->pants = NULL;
6749         skinframe->shirt = NULL;
6750         skinframe->nmap = NULL;
6751         skinframe->gloss = NULL;
6752         skinframe->glow = NULL;
6753         skinframe->fog = NULL;
6754         skinframe->reflect = NULL;
6755         skinframe->hasalpha = false;
6756
6757         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6758         if (!skindata)
6759                 return NULL;
6760
6761         if (developer_loading.integer)
6762                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6763
6764         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6765         {
6766                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6767                 temp2 = temp1 + width * height * 4;
6768                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6769                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6770                 Mem_Free(temp1);
6771         }
6772         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6773         if (textureflags & TEXF_ALPHA)
6774         {
6775                 for (i = 3;i < width * height * 4;i += 4)
6776                 {
6777                         if (skindata[i] < 255)
6778                         {
6779                                 skinframe->hasalpha = true;
6780                                 break;
6781                         }
6782                 }
6783                 if (r_loadfog && skinframe->hasalpha)
6784                 {
6785                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6786                         memcpy(fogpixels, skindata, width * height * 4);
6787                         for (i = 0;i < width * height * 4;i += 4)
6788                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6789                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6790                         Mem_Free(fogpixels);
6791                 }
6792         }
6793
6794         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6795         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6796
6797         return skinframe;
6798 }
6799
6800 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6801 {
6802         int i;
6803         int featuresmask;
6804         skinframe_t *skinframe;
6805
6806         if (cls.state == ca_dedicated)
6807                 return NULL;
6808
6809         // if already loaded just return it, otherwise make a new skinframe
6810         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6811         if (skinframe && skinframe->base)
6812                 return skinframe;
6813
6814         skinframe->stain = NULL;
6815         skinframe->merged = NULL;
6816         skinframe->base = NULL;
6817         skinframe->pants = NULL;
6818         skinframe->shirt = NULL;
6819         skinframe->nmap = NULL;
6820         skinframe->gloss = NULL;
6821         skinframe->glow = NULL;
6822         skinframe->fog = NULL;
6823         skinframe->reflect = NULL;
6824         skinframe->hasalpha = false;
6825
6826         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6827         if (!skindata)
6828                 return NULL;
6829
6830         if (developer_loading.integer)
6831                 Con_Printf("loading quake skin \"%s\"\n", name);
6832
6833         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
6834         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6835         memcpy(skinframe->qpixels, skindata, width*height);
6836         skinframe->qwidth = width;
6837         skinframe->qheight = height;
6838
6839         featuresmask = 0;
6840         for (i = 0;i < width * height;i++)
6841                 featuresmask |= palette_featureflags[skindata[i]];
6842
6843         skinframe->hasalpha = false;
6844         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6845         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6846         skinframe->qgeneratemerged = true;
6847         skinframe->qgeneratebase = skinframe->qhascolormapping;
6848         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6849
6850         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6851         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6852
6853         return skinframe;
6854 }
6855
6856 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6857 {
6858         int width;
6859         int height;
6860         unsigned char *skindata;
6861
6862         if (!skinframe->qpixels)
6863                 return;
6864
6865         if (!skinframe->qhascolormapping)
6866                 colormapped = false;
6867
6868         if (colormapped)
6869         {
6870                 if (!skinframe->qgeneratebase)
6871                         return;
6872         }
6873         else
6874         {
6875                 if (!skinframe->qgeneratemerged)
6876                         return;
6877         }
6878
6879         width = skinframe->qwidth;
6880         height = skinframe->qheight;
6881         skindata = skinframe->qpixels;
6882
6883         if (skinframe->qgeneratenmap)
6884         {
6885                 unsigned char *temp1, *temp2;
6886                 skinframe->qgeneratenmap = false;
6887                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6888                 temp2 = temp1 + width * height * 4;
6889                 // use either a custom palette or the quake palette
6890                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6891                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6892                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6893                 Mem_Free(temp1);
6894         }
6895
6896         if (skinframe->qgenerateglow)
6897         {
6898                 skinframe->qgenerateglow = false;
6899                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6900         }
6901
6902         if (colormapped)
6903         {
6904                 skinframe->qgeneratebase = false;
6905                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6906                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6907                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6908         }
6909         else
6910         {
6911                 skinframe->qgeneratemerged = false;
6912                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6913         }
6914
6915         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6916         {
6917                 Mem_Free(skinframe->qpixels);
6918                 skinframe->qpixels = NULL;
6919         }
6920 }
6921
6922 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
6923 {
6924         int i;
6925         skinframe_t *skinframe;
6926
6927         if (cls.state == ca_dedicated)
6928                 return NULL;
6929
6930         // if already loaded just return it, otherwise make a new skinframe
6931         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6932         if (skinframe && skinframe->base)
6933                 return skinframe;
6934
6935         skinframe->stain = NULL;
6936         skinframe->merged = NULL;
6937         skinframe->base = NULL;
6938         skinframe->pants = NULL;
6939         skinframe->shirt = NULL;
6940         skinframe->nmap = NULL;
6941         skinframe->gloss = NULL;
6942         skinframe->glow = NULL;
6943         skinframe->fog = NULL;
6944         skinframe->reflect = NULL;
6945         skinframe->hasalpha = false;
6946
6947         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6948         if (!skindata)
6949                 return NULL;
6950
6951         if (developer_loading.integer)
6952                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6953
6954         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6955         if (textureflags & TEXF_ALPHA)
6956         {
6957                 for (i = 0;i < width * height;i++)
6958                 {
6959                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6960                         {
6961                                 skinframe->hasalpha = true;
6962                                 break;
6963                         }
6964                 }
6965                 if (r_loadfog && skinframe->hasalpha)
6966                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6967         }
6968
6969         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6970         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
6971
6972         return skinframe;
6973 }
6974
6975 skinframe_t *R_SkinFrame_LoadMissing(void)
6976 {
6977         skinframe_t *skinframe;
6978
6979         if (cls.state == ca_dedicated)
6980                 return NULL;
6981
6982         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6983         skinframe->stain = NULL;
6984         skinframe->merged = NULL;
6985         skinframe->base = NULL;
6986         skinframe->pants = NULL;
6987         skinframe->shirt = NULL;
6988         skinframe->nmap = NULL;
6989         skinframe->gloss = NULL;
6990         skinframe->glow = NULL;
6991         skinframe->fog = NULL;
6992         skinframe->reflect = NULL;
6993         skinframe->hasalpha = false;
6994
6995         skinframe->avgcolor[0] = rand() / RAND_MAX;
6996         skinframe->avgcolor[1] = rand() / RAND_MAX;
6997         skinframe->avgcolor[2] = rand() / RAND_MAX;
6998         skinframe->avgcolor[3] = 1;
6999
7000         return skinframe;
7001 }
7002
7003 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7004 typedef struct suffixinfo_s
7005 {
7006         const char *suffix;
7007         qboolean flipx, flipy, flipdiagonal;
7008 }
7009 suffixinfo_t;
7010 static suffixinfo_t suffix[3][6] =
7011 {
7012         {
7013                 {"px",   false, false, false},
7014                 {"nx",   false, false, false},
7015                 {"py",   false, false, false},
7016                 {"ny",   false, false, false},
7017                 {"pz",   false, false, false},
7018                 {"nz",   false, false, false}
7019         },
7020         {
7021                 {"posx", false, false, false},
7022                 {"negx", false, false, false},
7023                 {"posy", false, false, false},
7024                 {"negy", false, false, false},
7025                 {"posz", false, false, false},
7026                 {"negz", false, false, false}
7027         },
7028         {
7029                 {"rt",    true, false,  true},
7030                 {"lf",   false,  true,  true},
7031                 {"ft",    true,  true, false},
7032                 {"bk",   false, false, false},
7033                 {"up",    true, false,  true},
7034                 {"dn",    true, false,  true}
7035         }
7036 };
7037
7038 static int componentorder[4] = {0, 1, 2, 3};
7039
7040 rtexture_t *R_LoadCubemap(const char *basename)
7041 {
7042         int i, j, cubemapsize;
7043         unsigned char *cubemappixels, *image_buffer;
7044         rtexture_t *cubemaptexture;
7045         char name[256];
7046         // must start 0 so the first loadimagepixels has no requested width/height
7047         cubemapsize = 0;
7048         cubemappixels = NULL;
7049         cubemaptexture = NULL;
7050         // keep trying different suffix groups (posx, px, rt) until one loads
7051         for (j = 0;j < 3 && !cubemappixels;j++)
7052         {
7053                 // load the 6 images in the suffix group
7054                 for (i = 0;i < 6;i++)
7055                 {
7056                         // generate an image name based on the base and and suffix
7057                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7058                         // load it
7059                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7060                         {
7061                                 // an image loaded, make sure width and height are equal
7062                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7063                                 {
7064                                         // if this is the first image to load successfully, allocate the cubemap memory
7065                                         if (!cubemappixels && image_width >= 1)
7066                                         {
7067                                                 cubemapsize = image_width;
7068                                                 // note this clears to black, so unavailable sides are black
7069                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7070                                         }
7071                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7072                                         if (cubemappixels)
7073                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
7074                                 }
7075                                 else
7076                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7077                                 // free the image
7078                                 Mem_Free(image_buffer);
7079                         }
7080                 }
7081         }
7082         // if a cubemap loaded, upload it
7083         if (cubemappixels)
7084         {
7085                 if (developer_loading.integer)
7086                         Con_Printf("loading cubemap \"%s\"\n", basename);
7087
7088                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7089                 Mem_Free(cubemappixels);
7090         }
7091         else
7092         {
7093                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7094                 if (developer_loading.integer)
7095                 {
7096                         Con_Printf("(tried tried images ");
7097                         for (j = 0;j < 3;j++)
7098                                 for (i = 0;i < 6;i++)
7099                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7100                         Con_Print(" and was unable to find any of them).\n");
7101                 }
7102         }
7103         return cubemaptexture;
7104 }
7105
7106 rtexture_t *R_GetCubemap(const char *basename)
7107 {
7108         int i;
7109         for (i = 0;i < r_texture_numcubemaps;i++)
7110                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7111                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7112         if (i >= MAX_CUBEMAPS)
7113                 return r_texture_whitecube;
7114         r_texture_numcubemaps++;
7115         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7116         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7117         return r_texture_cubemaps[i].texture;
7118 }
7119
7120 void R_FreeCubemaps(void)
7121 {
7122         int i;
7123         for (i = 0;i < r_texture_numcubemaps;i++)
7124         {
7125                 if (developer_loading.integer)
7126                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7127                 if (r_texture_cubemaps[i].texture)
7128                         R_FreeTexture(r_texture_cubemaps[i].texture);
7129         }
7130         r_texture_numcubemaps = 0;
7131 }
7132
7133 void R_Main_FreeViewCache(void)
7134 {
7135         if (r_refdef.viewcache.entityvisible)
7136                 Mem_Free(r_refdef.viewcache.entityvisible);
7137         if (r_refdef.viewcache.world_pvsbits)
7138                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7139         if (r_refdef.viewcache.world_leafvisible)
7140                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7141         if (r_refdef.viewcache.world_surfacevisible)
7142                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7143         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7144 }
7145
7146 void R_Main_ResizeViewCache(void)
7147 {
7148         int numentities = r_refdef.scene.numentities;
7149         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7150         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7151         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7152         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7153         if (r_refdef.viewcache.maxentities < numentities)
7154         {
7155                 r_refdef.viewcache.maxentities = numentities;
7156                 if (r_refdef.viewcache.entityvisible)
7157                         Mem_Free(r_refdef.viewcache.entityvisible);
7158                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7159         }
7160         if (r_refdef.viewcache.world_numclusters != numclusters)
7161         {
7162                 r_refdef.viewcache.world_numclusters = numclusters;
7163                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7164                 if (r_refdef.viewcache.world_pvsbits)
7165                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7166                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7167         }
7168         if (r_refdef.viewcache.world_numleafs != numleafs)
7169         {
7170                 r_refdef.viewcache.world_numleafs = numleafs;
7171                 if (r_refdef.viewcache.world_leafvisible)
7172                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7173                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7174         }
7175         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7176         {
7177                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7178                 if (r_refdef.viewcache.world_surfacevisible)
7179                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7180                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7181         }
7182 }
7183
7184 extern rtexture_t *loadingscreentexture;
7185 void gl_main_start(void)
7186 {
7187         loadingscreentexture = NULL;
7188         r_texture_blanknormalmap = NULL;
7189         r_texture_white = NULL;
7190         r_texture_grey128 = NULL;
7191         r_texture_black = NULL;
7192         r_texture_whitecube = NULL;
7193         r_texture_normalizationcube = NULL;
7194         r_texture_fogattenuation = NULL;
7195         r_texture_fogheighttexture = NULL;
7196         r_texture_gammaramps = NULL;
7197         r_texture_numcubemaps = 0;
7198
7199         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7200         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7201
7202         switch(vid.renderpath)
7203         {
7204         case RENDERPATH_GL20:
7205         case RENDERPATH_CGGL:
7206         case RENDERPATH_D3D9:
7207         case RENDERPATH_D3D10:
7208         case RENDERPATH_D3D11:
7209                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7210                 Cvar_SetValueQuick(&gl_combine, 1);
7211                 Cvar_SetValueQuick(&r_glsl, 1);
7212                 r_loadnormalmap = true;
7213                 r_loadgloss = true;
7214                 r_loadfog = false;
7215                 break;
7216         case RENDERPATH_GL13:
7217                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7218                 Cvar_SetValueQuick(&gl_combine, 1);
7219                 Cvar_SetValueQuick(&r_glsl, 0);
7220                 r_loadnormalmap = false;
7221                 r_loadgloss = false;
7222                 r_loadfog = true;
7223                 break;
7224         case RENDERPATH_GL11:
7225                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7226                 Cvar_SetValueQuick(&gl_combine, 0);
7227                 Cvar_SetValueQuick(&r_glsl, 0);
7228                 r_loadnormalmap = false;
7229                 r_loadgloss = false;
7230                 r_loadfog = true;
7231                 break;
7232         }
7233
7234         R_AnimCache_Free();
7235         R_FrameData_Reset();
7236
7237         r_numqueries = 0;
7238         r_maxqueries = 0;
7239         memset(r_queries, 0, sizeof(r_queries));
7240
7241         r_qwskincache = NULL;
7242         r_qwskincache_size = 0;
7243
7244         // set up r_skinframe loading system for textures
7245         memset(&r_skinframe, 0, sizeof(r_skinframe));
7246         r_skinframe.loadsequence = 1;
7247         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7248
7249         r_main_texturepool = R_AllocTexturePool();
7250         R_BuildBlankTextures();
7251         R_BuildNoTexture();
7252         if (vid.support.arb_texture_cube_map)
7253         {
7254                 R_BuildWhiteCube();
7255                 R_BuildNormalizationCube();
7256         }
7257         r_texture_fogattenuation = NULL;
7258         r_texture_fogheighttexture = NULL;
7259         r_texture_gammaramps = NULL;
7260         //r_texture_fogintensity = NULL;
7261         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7262         memset(&r_waterstate, 0, sizeof(r_waterstate));
7263         r_glsl_permutation = NULL;
7264         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7265         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7266         glslshaderstring = NULL;
7267 #ifdef SUPPORTCG
7268         r_cg_permutation = NULL;
7269         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7270         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7271         cgshaderstring = NULL;
7272 #endif
7273 #ifdef SUPPORTD3D
7274         r_hlsl_permutation = NULL;
7275         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7276         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7277         hlslshaderstring = NULL;
7278 #endif
7279         memset(&r_svbsp, 0, sizeof (r_svbsp));
7280
7281         r_refdef.fogmasktable_density = 0;
7282 }
7283
7284 void gl_main_shutdown(void)
7285 {
7286         R_AnimCache_Free();
7287         R_FrameData_Reset();
7288
7289         R_Main_FreeViewCache();
7290
7291         switch(vid.renderpath)
7292         {
7293         case RENDERPATH_GL11:
7294         case RENDERPATH_GL13:
7295         case RENDERPATH_GL20:
7296         case RENDERPATH_CGGL:
7297                 if (r_maxqueries)
7298                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7299                 break;
7300         case RENDERPATH_D3D9:
7301                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7302                 break;
7303         case RENDERPATH_D3D10:
7304                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7305                 break;
7306         case RENDERPATH_D3D11:
7307                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7308                 break;
7309         }
7310
7311         r_numqueries = 0;
7312         r_maxqueries = 0;
7313         memset(r_queries, 0, sizeof(r_queries));
7314
7315         r_qwskincache = NULL;
7316         r_qwskincache_size = 0;
7317
7318         // clear out the r_skinframe state
7319         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7320         memset(&r_skinframe, 0, sizeof(r_skinframe));
7321
7322         if (r_svbsp.nodes)
7323                 Mem_Free(r_svbsp.nodes);
7324         memset(&r_svbsp, 0, sizeof (r_svbsp));
7325         R_FreeTexturePool(&r_main_texturepool);
7326         loadingscreentexture = NULL;
7327         r_texture_blanknormalmap = NULL;
7328         r_texture_white = NULL;
7329         r_texture_grey128 = NULL;
7330         r_texture_black = NULL;
7331         r_texture_whitecube = NULL;
7332         r_texture_normalizationcube = NULL;
7333         r_texture_fogattenuation = NULL;
7334         r_texture_fogheighttexture = NULL;
7335         r_texture_gammaramps = NULL;
7336         r_texture_numcubemaps = 0;
7337         //r_texture_fogintensity = NULL;
7338         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7339         memset(&r_waterstate, 0, sizeof(r_waterstate));
7340         R_GLSL_Restart_f();
7341 }
7342
7343 extern void CL_ParseEntityLump(char *entitystring);
7344 void gl_main_newmap(void)
7345 {
7346         // FIXME: move this code to client
7347         char *entities, entname[MAX_QPATH];
7348         if (r_qwskincache)
7349                 Mem_Free(r_qwskincache);
7350         r_qwskincache = NULL;
7351         r_qwskincache_size = 0;
7352         if (cl.worldmodel)
7353         {
7354                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7355                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7356                 {
7357                         CL_ParseEntityLump(entities);
7358                         Mem_Free(entities);
7359                         return;
7360                 }
7361                 if (cl.worldmodel->brush.entities)
7362                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7363         }
7364         R_Main_FreeViewCache();
7365
7366         R_FrameData_Reset();
7367 }
7368
7369 void GL_Main_Init(void)
7370 {
7371         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7372
7373         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7374         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7375         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7376         if (gamemode == GAME_NEHAHRA)
7377         {
7378                 Cvar_RegisterVariable (&gl_fogenable);
7379                 Cvar_RegisterVariable (&gl_fogdensity);
7380                 Cvar_RegisterVariable (&gl_fogred);
7381                 Cvar_RegisterVariable (&gl_foggreen);
7382                 Cvar_RegisterVariable (&gl_fogblue);
7383                 Cvar_RegisterVariable (&gl_fogstart);
7384                 Cvar_RegisterVariable (&gl_fogend);
7385                 Cvar_RegisterVariable (&gl_skyclip);
7386         }
7387         Cvar_RegisterVariable(&r_motionblur);
7388         Cvar_RegisterVariable(&r_motionblur_maxblur);
7389         Cvar_RegisterVariable(&r_motionblur_bmin);
7390         Cvar_RegisterVariable(&r_motionblur_vmin);
7391         Cvar_RegisterVariable(&r_motionblur_vmax);
7392         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7393         Cvar_RegisterVariable(&r_motionblur_randomize);
7394         Cvar_RegisterVariable(&r_damageblur);
7395         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7396         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7397         Cvar_RegisterVariable(&r_equalize_entities_by);
7398         Cvar_RegisterVariable(&r_equalize_entities_to);
7399         Cvar_RegisterVariable(&r_depthfirst);
7400         Cvar_RegisterVariable(&r_useinfinitefarclip);
7401         Cvar_RegisterVariable(&r_farclip_base);
7402         Cvar_RegisterVariable(&r_farclip_world);
7403         Cvar_RegisterVariable(&r_nearclip);
7404         Cvar_RegisterVariable(&r_showbboxes);
7405         Cvar_RegisterVariable(&r_showsurfaces);
7406         Cvar_RegisterVariable(&r_showtris);
7407         Cvar_RegisterVariable(&r_shownormals);
7408         Cvar_RegisterVariable(&r_showlighting);
7409         Cvar_RegisterVariable(&r_showshadowvolumes);
7410         Cvar_RegisterVariable(&r_showcollisionbrushes);
7411         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7412         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7413         Cvar_RegisterVariable(&r_showdisabledepthtest);
7414         Cvar_RegisterVariable(&r_drawportals);
7415         Cvar_RegisterVariable(&r_drawentities);
7416         Cvar_RegisterVariable(&r_draw2d);
7417         Cvar_RegisterVariable(&r_drawworld);
7418         Cvar_RegisterVariable(&r_cullentities_trace);
7419         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7420         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7421         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7422         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7423         Cvar_RegisterVariable(&r_drawviewmodel);
7424         Cvar_RegisterVariable(&r_drawexteriormodel);
7425         Cvar_RegisterVariable(&r_speeds);
7426         Cvar_RegisterVariable(&r_fullbrights);
7427         Cvar_RegisterVariable(&r_wateralpha);
7428         Cvar_RegisterVariable(&r_dynamic);
7429         Cvar_RegisterVariable(&r_fullbright);
7430         Cvar_RegisterVariable(&r_shadows);
7431         Cvar_RegisterVariable(&r_shadows_darken);
7432         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7433         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7434         Cvar_RegisterVariable(&r_shadows_throwdistance);
7435         Cvar_RegisterVariable(&r_shadows_throwdirection);
7436         Cvar_RegisterVariable(&r_shadows_focus);
7437         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7438         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7439         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7440         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7441         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7442         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7443         Cvar_RegisterVariable(&r_fog_exp2);
7444         Cvar_RegisterVariable(&r_drawfog);
7445         Cvar_RegisterVariable(&r_transparentdepthmasking);
7446         Cvar_RegisterVariable(&r_texture_dds_load);
7447         Cvar_RegisterVariable(&r_texture_dds_save);
7448         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7449         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7450         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7451         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7452         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7453         Cvar_RegisterVariable(&r_textureunits);
7454         Cvar_RegisterVariable(&gl_combine);
7455         Cvar_RegisterVariable(&r_glsl);
7456         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7457         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7458         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7459         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7460         Cvar_RegisterVariable(&r_glsl_postprocess);
7461         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7462         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7463         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7464         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7465         Cvar_RegisterVariable(&r_water);
7466         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7467         Cvar_RegisterVariable(&r_water_clippingplanebias);
7468         Cvar_RegisterVariable(&r_water_refractdistort);
7469         Cvar_RegisterVariable(&r_water_reflectdistort);
7470         Cvar_RegisterVariable(&r_lerpsprites);
7471         Cvar_RegisterVariable(&r_lerpmodels);
7472         Cvar_RegisterVariable(&r_lerplightstyles);
7473         Cvar_RegisterVariable(&r_waterscroll);
7474         Cvar_RegisterVariable(&r_bloom);
7475         Cvar_RegisterVariable(&r_bloom_colorscale);
7476         Cvar_RegisterVariable(&r_bloom_brighten);
7477         Cvar_RegisterVariable(&r_bloom_blur);
7478         Cvar_RegisterVariable(&r_bloom_resolution);
7479         Cvar_RegisterVariable(&r_bloom_colorexponent);
7480         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7481         Cvar_RegisterVariable(&r_hdr);
7482         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7483         Cvar_RegisterVariable(&r_hdr_glowintensity);
7484         Cvar_RegisterVariable(&r_hdr_range);
7485         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7486         Cvar_RegisterVariable(&developer_texturelogging);
7487         Cvar_RegisterVariable(&gl_lightmaps);
7488         Cvar_RegisterVariable(&r_test);
7489         Cvar_RegisterVariable(&r_glsl_saturation);
7490         Cvar_RegisterVariable(&r_framedatasize);
7491         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7492                 Cvar_SetValue("r_fullbrights", 0);
7493         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7494
7495         Cvar_RegisterVariable(&r_track_sprites);
7496         Cvar_RegisterVariable(&r_track_sprites_flags);
7497         Cvar_RegisterVariable(&r_track_sprites_scalew);
7498         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7499         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7500         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7501 }
7502
7503 extern void R_Textures_Init(void);
7504 extern void GL_Draw_Init(void);
7505 extern void GL_Main_Init(void);
7506 extern void R_Shadow_Init(void);
7507 extern void R_Sky_Init(void);
7508 extern void GL_Surf_Init(void);
7509 extern void R_Particles_Init(void);
7510 extern void R_Explosion_Init(void);
7511 extern void gl_backend_init(void);
7512 extern void Sbar_Init(void);
7513 extern void R_LightningBeams_Init(void);
7514 extern void Mod_RenderInit(void);
7515 extern void Font_Init(void);
7516
7517 void Render_Init(void)
7518 {
7519         gl_backend_init();
7520         R_Textures_Init();
7521         GL_Main_Init();
7522         Font_Init();
7523         GL_Draw_Init();
7524         R_Shadow_Init();
7525         R_Sky_Init();
7526         GL_Surf_Init();
7527         Sbar_Init();
7528         R_Particles_Init();
7529         R_Explosion_Init();
7530         R_LightningBeams_Init();
7531         Mod_RenderInit();
7532 }
7533
7534 /*
7535 ===============
7536 GL_Init
7537 ===============
7538 */
7539 extern char *ENGINE_EXTENSIONS;
7540 void GL_Init (void)
7541 {
7542         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7543         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7544         gl_version = (const char *)qglGetString(GL_VERSION);
7545         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7546
7547         if (!gl_extensions)
7548                 gl_extensions = "";
7549         if (!gl_platformextensions)
7550                 gl_platformextensions = "";
7551
7552         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7553         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7554         Con_Printf("GL_VERSION: %s\n", gl_version);
7555         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7556         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7557
7558         VID_CheckExtensions();
7559
7560         // LordHavoc: report supported extensions
7561         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7562
7563         // clear to black (loading plaque will be seen over this)
7564         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7565 }
7566
7567 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7568 {
7569         int i;
7570         mplane_t *p;
7571         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7572         {
7573                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7574                 if (i == 4)
7575                         continue;
7576                 p = r_refdef.view.frustum + i;
7577                 switch(p->signbits)
7578                 {
7579                 default:
7580                 case 0:
7581                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7582                                 return true;
7583                         break;
7584                 case 1:
7585                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7586                                 return true;
7587                         break;
7588                 case 2:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 3:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 4:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 5:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 6:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 7:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 }
7613         }
7614         return false;
7615 }
7616
7617 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7618 {
7619         int i;
7620         const mplane_t *p;
7621         for (i = 0;i < numplanes;i++)
7622         {
7623                 p = planes + i;
7624                 switch(p->signbits)
7625                 {
7626                 default:
7627                 case 0:
7628                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7629                                 return true;
7630                         break;
7631                 case 1:
7632                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7633                                 return true;
7634                         break;
7635                 case 2:
7636                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7637                                 return true;
7638                         break;
7639                 case 3:
7640                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7641                                 return true;
7642                         break;
7643                 case 4:
7644                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7645                                 return true;
7646                         break;
7647                 case 5:
7648                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7649                                 return true;
7650                         break;
7651                 case 6:
7652                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7653                                 return true;
7654                         break;
7655                 case 7:
7656                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7657                                 return true;
7658                         break;
7659                 }
7660         }
7661         return false;
7662 }
7663
7664 //==================================================================================
7665
7666 // LordHavoc: this stores temporary data used within the same frame
7667
7668 qboolean r_framedata_failed;
7669 static size_t r_framedata_size;
7670 static size_t r_framedata_current;
7671 static void *r_framedata_base;
7672
7673 void R_FrameData_Reset(void)
7674 {
7675         if (r_framedata_base)
7676                 Mem_Free(r_framedata_base);
7677         r_framedata_base = NULL;
7678         r_framedata_size = 0;
7679         r_framedata_current = 0;
7680         r_framedata_failed = false;
7681 }
7682
7683 void R_FrameData_NewFrame(void)
7684 {
7685         size_t wantedsize;
7686         if (r_framedata_failed)
7687                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7688         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7689         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7690         if (r_framedata_size != wantedsize)
7691         {
7692                 r_framedata_size = wantedsize;
7693                 if (r_framedata_base)
7694                         Mem_Free(r_framedata_base);
7695                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7696         }
7697         r_framedata_current = 0;
7698         r_framedata_failed = false;
7699 }
7700
7701 void *R_FrameData_Alloc(size_t size)
7702 {
7703         void *data;
7704
7705         // align to 16 byte boundary
7706         size = (size + 15) & ~15;
7707         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7708         r_framedata_current += size;
7709
7710         // check overflow
7711         if (r_framedata_current > r_framedata_size)
7712                 r_framedata_failed = true;
7713
7714         // return NULL on everything after a failure
7715         if (r_framedata_failed)
7716                 return NULL;
7717
7718         return data;
7719 }
7720
7721 void *R_FrameData_Store(size_t size, void *data)
7722 {
7723         void *d = R_FrameData_Alloc(size);
7724         if (d)
7725                 memcpy(d, data, size);
7726         return d;
7727 }
7728
7729 //==================================================================================
7730
7731 // LordHavoc: animcache originally written by Echon, rewritten since then
7732
7733 /**
7734  * Animation cache prevents re-generating mesh data for an animated model
7735  * multiple times in one frame for lighting, shadowing, reflections, etc.
7736  */
7737
7738 void R_AnimCache_Free(void)
7739 {
7740 }
7741
7742 void R_AnimCache_ClearCache(void)
7743 {
7744         int i;
7745         entity_render_t *ent;
7746
7747         for (i = 0;i < r_refdef.scene.numentities;i++)
7748         {
7749                 ent = r_refdef.scene.entities[i];
7750                 ent->animcache_vertex3f = NULL;
7751                 ent->animcache_normal3f = NULL;
7752                 ent->animcache_svector3f = NULL;
7753                 ent->animcache_tvector3f = NULL;
7754                 ent->animcache_vertexposition = NULL;
7755                 ent->animcache_vertexmesh = NULL;
7756                 ent->animcache_vertexpositionbuffer = NULL;
7757                 ent->animcache_vertexmeshbuffer = NULL;
7758         }
7759 }
7760
7761 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7762 {
7763         int i;
7764         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7765                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7766         if (!ent->animcache_vertexposition)
7767                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7768         if (ent->animcache_vertexposition)
7769         {
7770                 for (i = 0;i < numvertices;i++)
7771                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
7772                 // TODO: upload vertex buffer?
7773         }
7774         if (ent->animcache_vertexmesh)
7775         {
7776                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7777                 for (i = 0;i < numvertices;i++)
7778                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
7779                 if (ent->animcache_svector3f)
7780                         for (i = 0;i < numvertices;i++)
7781                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
7782                 if (ent->animcache_tvector3f)
7783                         for (i = 0;i < numvertices;i++)
7784                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
7785                 if (ent->animcache_normal3f)
7786                         for (i = 0;i < numvertices;i++)
7787                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
7788                 // TODO: upload vertex buffer?
7789         }
7790 }
7791
7792 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7793 {
7794         dp_model_t *model = ent->model;
7795         int numvertices;
7796         // see if it's already cached this frame
7797         if (ent->animcache_vertex3f)
7798         {
7799                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7800                 if (wantnormals || wanttangents)
7801                 {
7802                         if (ent->animcache_normal3f)
7803                                 wantnormals = false;
7804                         if (ent->animcache_svector3f)
7805                                 wanttangents = false;
7806                         if (wantnormals || wanttangents)
7807                         {
7808                                 numvertices = model->surfmesh.num_vertices;
7809                                 if (wantnormals)
7810                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7811                                 if (wanttangents)
7812                                 {
7813                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815                                 }
7816                                 if (!r_framedata_failed)
7817                                 {
7818                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7819                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7820                                 }
7821                         }
7822                 }
7823         }
7824         else
7825         {
7826                 // see if this ent is worth caching
7827                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7828                         return false;
7829                 // get some memory for this entity and generate mesh data
7830                 numvertices = model->surfmesh.num_vertices;
7831                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7832                 if (wantnormals)
7833                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7834                 if (wanttangents)
7835                 {
7836                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7837                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7838                 }
7839                 if (!r_framedata_failed)
7840                 {
7841                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7842                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7843                 }
7844         }
7845         return !r_framedata_failed;
7846 }
7847
7848 void R_AnimCache_CacheVisibleEntities(void)
7849 {
7850         int i;
7851         qboolean wantnormals = true;
7852         qboolean wanttangents = !r_showsurfaces.integer;
7853
7854         switch(vid.renderpath)
7855         {
7856         case RENDERPATH_GL20:
7857         case RENDERPATH_CGGL:
7858         case RENDERPATH_D3D9:
7859         case RENDERPATH_D3D10:
7860         case RENDERPATH_D3D11:
7861                 break;
7862         case RENDERPATH_GL13:
7863         case RENDERPATH_GL11:
7864                 wanttangents = false;
7865                 break;
7866         }
7867
7868         if (r_shownormals.integer)
7869                 wanttangents = wantnormals = true;
7870
7871         // TODO: thread this
7872         // NOTE: R_PrepareRTLights() also caches entities
7873
7874         for (i = 0;i < r_refdef.scene.numentities;i++)
7875                 if (r_refdef.viewcache.entityvisible[i])
7876                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7877 }
7878
7879 //==================================================================================
7880
7881 static void R_View_UpdateEntityLighting (void)
7882 {
7883         int i;
7884         entity_render_t *ent;
7885         vec3_t tempdiffusenormal, avg;
7886         vec_t f, fa, fd, fdd;
7887         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7888
7889         for (i = 0;i < r_refdef.scene.numentities;i++)
7890         {
7891                 ent = r_refdef.scene.entities[i];
7892
7893                 // skip unseen models
7894                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7895                         continue;
7896
7897                 // skip bsp models
7898                 if (ent->model && ent->model->brush.num_leafs)
7899                 {
7900                         // TODO: use modellight for r_ambient settings on world?
7901                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7902                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7903                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7904                         continue;
7905                 }
7906
7907                 // fetch the lighting from the worldmodel data
7908                 VectorClear(ent->modellight_ambient);
7909                 VectorClear(ent->modellight_diffuse);
7910                 VectorClear(tempdiffusenormal);
7911                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7912                 {
7913                         vec3_t org;
7914                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7915                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7916                         if(ent->flags & RENDER_EQUALIZE)
7917                         {
7918                                 // first fix up ambient lighting...
7919                                 if(r_equalize_entities_minambient.value > 0)
7920                                 {
7921                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7922                                         if(fd > 0)
7923                                         {
7924                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7925                                                 if(fa < r_equalize_entities_minambient.value * fd)
7926                                                 {
7927                                                         // solve:
7928                                                         //   fa'/fd' = minambient
7929                                                         //   fa'+0.25*fd' = fa+0.25*fd
7930                                                         //   ...
7931                                                         //   fa' = fd' * minambient
7932                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7933                                                         //   ...
7934                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7935                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7936                                                         //   ...
7937                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7938                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
7939                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7940                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7941                                                 }
7942                                         }
7943                                 }
7944
7945                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7946                                 {
7947                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7948                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7949                                         if(f > 0)
7950                                         {
7951                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7952                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7953                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7954                                         }
7955                                 }
7956                         }
7957                 }
7958                 else // highly rare
7959                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7960
7961                 // move the light direction into modelspace coordinates for lighting code
7962                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7963                 if(VectorLength2(ent->modellight_lightdir) == 0)
7964                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7965                 VectorNormalize(ent->modellight_lightdir);
7966         }
7967 }
7968
7969 #define MAX_LINEOFSIGHTTRACES 64
7970
7971 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7972 {
7973         int i;
7974         vec3_t boxmins, boxmaxs;
7975         vec3_t start;
7976         vec3_t end;
7977         dp_model_t *model = r_refdef.scene.worldmodel;
7978
7979         if (!model || !model->brush.TraceLineOfSight)
7980                 return true;
7981
7982         // expand the box a little
7983         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7984         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7985         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7986         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7987         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7988         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7989
7990         // return true if eye is inside enlarged box
7991         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7992                 return true;
7993
7994         // try center
7995         VectorCopy(eye, start);
7996         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7997         if (model->brush.TraceLineOfSight(model, start, end))
7998                 return true;
7999
8000         // try various random positions
8001         for (i = 0;i < numsamples;i++)
8002         {
8003                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8004                 if (model->brush.TraceLineOfSight(model, start, end))
8005                         return true;
8006         }
8007
8008         return false;
8009 }
8010
8011
8012 static void R_View_UpdateEntityVisible (void)
8013 {
8014         int i;
8015         int renderimask;
8016         int samples;
8017         entity_render_t *ent;
8018
8019         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8020                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8021                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8022                 :                                                          RENDER_EXTERIORMODEL;
8023         if (!r_drawviewmodel.integer)
8024                 renderimask |= RENDER_VIEWMODEL;
8025         if (!r_drawexteriormodel.integer)
8026                 renderimask |= RENDER_EXTERIORMODEL;
8027         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8028         {
8029                 // worldmodel can check visibility
8030                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8031                 for (i = 0;i < r_refdef.scene.numentities;i++)
8032                 {
8033                         ent = r_refdef.scene.entities[i];
8034                         if (!(ent->flags & renderimask))
8035                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8036                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
8037                                 r_refdef.viewcache.entityvisible[i] = true;
8038                 }
8039                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8040                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8041                 {
8042                         for (i = 0;i < r_refdef.scene.numentities;i++)
8043                         {
8044                                 ent = r_refdef.scene.entities[i];
8045                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8046                                 {
8047                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8048                                         if (samples < 0)
8049                                                 continue; // temp entities do pvs only
8050                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8051                                                 ent->last_trace_visibility = realtime;
8052                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8053                                                 r_refdef.viewcache.entityvisible[i] = 0;
8054                                 }
8055                         }
8056                 }
8057         }
8058         else
8059         {
8060                 // no worldmodel or it can't check visibility
8061                 for (i = 0;i < r_refdef.scene.numentities;i++)
8062                 {
8063                         ent = r_refdef.scene.entities[i];
8064                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
8065                 }
8066         }
8067 }
8068
8069 /// only used if skyrendermasked, and normally returns false
8070 int R_DrawBrushModelsSky (void)
8071 {
8072         int i, sky;
8073         entity_render_t *ent;
8074
8075         sky = false;
8076         for (i = 0;i < r_refdef.scene.numentities;i++)
8077         {
8078                 if (!r_refdef.viewcache.entityvisible[i])
8079                         continue;
8080                 ent = r_refdef.scene.entities[i];
8081                 if (!ent->model || !ent->model->DrawSky)
8082                         continue;
8083                 ent->model->DrawSky(ent);
8084                 sky = true;
8085         }
8086         return sky;
8087 }
8088
8089 static void R_DrawNoModel(entity_render_t *ent);
8090 static void R_DrawModels(void)
8091 {
8092         int i;
8093         entity_render_t *ent;
8094
8095         for (i = 0;i < r_refdef.scene.numentities;i++)
8096         {
8097                 if (!r_refdef.viewcache.entityvisible[i])
8098                         continue;
8099                 ent = r_refdef.scene.entities[i];
8100                 r_refdef.stats.entities++;
8101                 if (ent->model && ent->model->Draw != NULL)
8102                         ent->model->Draw(ent);
8103                 else
8104                         R_DrawNoModel(ent);
8105         }
8106 }
8107
8108 static void R_DrawModelsDepth(void)
8109 {
8110         int i;
8111         entity_render_t *ent;
8112
8113         for (i = 0;i < r_refdef.scene.numentities;i++)
8114         {
8115                 if (!r_refdef.viewcache.entityvisible[i])
8116                         continue;
8117                 ent = r_refdef.scene.entities[i];
8118                 if (ent->model && ent->model->DrawDepth != NULL)
8119                         ent->model->DrawDepth(ent);
8120         }
8121 }
8122
8123 static void R_DrawModelsDebug(void)
8124 {
8125         int i;
8126         entity_render_t *ent;
8127
8128         for (i = 0;i < r_refdef.scene.numentities;i++)
8129         {
8130                 if (!r_refdef.viewcache.entityvisible[i])
8131                         continue;
8132                 ent = r_refdef.scene.entities[i];
8133                 if (ent->model && ent->model->DrawDebug != NULL)
8134                         ent->model->DrawDebug(ent);
8135         }
8136 }
8137
8138 static void R_DrawModelsAddWaterPlanes(void)
8139 {
8140         int i;
8141         entity_render_t *ent;
8142
8143         for (i = 0;i < r_refdef.scene.numentities;i++)
8144         {
8145                 if (!r_refdef.viewcache.entityvisible[i])
8146                         continue;
8147                 ent = r_refdef.scene.entities[i];
8148                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8149                         ent->model->DrawAddWaterPlanes(ent);
8150         }
8151 }
8152
8153 static void R_View_SetFrustum(void)
8154 {
8155         int i;
8156         double slopex, slopey;
8157         vec3_t forward, left, up, origin;
8158
8159         // we can't trust r_refdef.view.forward and friends in reflected scenes
8160         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8161
8162 #if 0
8163         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8164         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8165         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8166         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8167         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8168         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8169         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8170         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8171         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8172         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8173         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8174         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8175 #endif
8176
8177 #if 0
8178         zNear = r_refdef.nearclip;
8179         nudge = 1.0 - 1.0 / (1<<23);
8180         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8181         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8182         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8183         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8184         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8185         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8186         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8187         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8188 #endif
8189
8190
8191
8192 #if 0
8193         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8194         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8195         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8196         r_refdef.view.frustum[0].dist = m[15] - m[12];
8197
8198         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8199         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8200         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8201         r_refdef.view.frustum[1].dist = m[15] + m[12];
8202
8203         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8204         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8205         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8206         r_refdef.view.frustum[2].dist = m[15] - m[13];
8207
8208         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8209         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8210         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8211         r_refdef.view.frustum[3].dist = m[15] + m[13];
8212
8213         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8214         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8215         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8216         r_refdef.view.frustum[4].dist = m[15] - m[14];
8217
8218         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8219         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8220         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8221         r_refdef.view.frustum[5].dist = m[15] + m[14];
8222 #endif
8223
8224         if (r_refdef.view.useperspective)
8225         {
8226                 slopex = 1.0 / r_refdef.view.frustum_x;
8227                 slopey = 1.0 / r_refdef.view.frustum_y;
8228                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8229                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8230                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8231                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8232                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8233
8234                 // Leaving those out was a mistake, those were in the old code, and they
8235                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8236                 // I couldn't reproduce it after adding those normalizations. --blub
8237                 VectorNormalize(r_refdef.view.frustum[0].normal);
8238                 VectorNormalize(r_refdef.view.frustum[1].normal);
8239                 VectorNormalize(r_refdef.view.frustum[2].normal);
8240                 VectorNormalize(r_refdef.view.frustum[3].normal);
8241
8242                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8243                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8244                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8245                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8246                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8247
8248                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8249                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8250                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8251                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8252                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8253         }
8254         else
8255         {
8256                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8257                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8258                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8259                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8260                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8261                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8262                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8263                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8264                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8265                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8266         }
8267         r_refdef.view.numfrustumplanes = 5;
8268
8269         if (r_refdef.view.useclipplane)
8270         {
8271                 r_refdef.view.numfrustumplanes = 6;
8272                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8273         }
8274
8275         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8276                 PlaneClassify(r_refdef.view.frustum + i);
8277
8278         // LordHavoc: note to all quake engine coders, Quake had a special case
8279         // for 90 degrees which assumed a square view (wrong), so I removed it,
8280         // Quake2 has it disabled as well.
8281
8282         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8283         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8284         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8285         //PlaneClassify(&frustum[0]);
8286
8287         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8288         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8289         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8290         //PlaneClassify(&frustum[1]);
8291
8292         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8293         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8294         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8295         //PlaneClassify(&frustum[2]);
8296
8297         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8298         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8299         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8300         //PlaneClassify(&frustum[3]);
8301
8302         // nearclip plane
8303         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8304         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8305         //PlaneClassify(&frustum[4]);
8306 }
8307
8308 void R_View_Update(void)
8309 {
8310         R_Main_ResizeViewCache();
8311         R_View_SetFrustum();
8312         R_View_WorldVisibility(r_refdef.view.useclipplane);
8313         R_View_UpdateEntityVisible();
8314         R_View_UpdateEntityLighting();
8315 }
8316
8317 void R_SetupView(qboolean allowwaterclippingplane)
8318 {
8319         const float *customclipplane = NULL;
8320         float plane[4];
8321         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8322         {
8323                 // LordHavoc: couldn't figure out how to make this approach the
8324                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8325                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8326                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8327                         dist = r_refdef.view.clipplane.dist;
8328                 plane[0] = r_refdef.view.clipplane.normal[0];
8329                 plane[1] = r_refdef.view.clipplane.normal[1];
8330                 plane[2] = r_refdef.view.clipplane.normal[2];
8331                 plane[3] = dist;
8332                 customclipplane = plane;
8333         }
8334
8335         if (!r_refdef.view.useperspective)
8336                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
8337         else if (vid.stencil && r_useinfinitefarclip.integer)
8338                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
8339         else
8340                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
8341         R_SetViewport(&r_refdef.view.viewport);
8342 }
8343
8344 void R_EntityMatrix(const matrix4x4_t *matrix)
8345 {
8346         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8347         {
8348                 gl_modelmatrixchanged = false;
8349                 gl_modelmatrix = *matrix;
8350                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8351                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8352                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8353                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8354                 CHECKGLERROR
8355                 switch(vid.renderpath)
8356                 {
8357                 case RENDERPATH_D3D9:
8358 #ifdef SUPPORTD3D
8359                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8360                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8361 #endif
8362                         break;
8363                 case RENDERPATH_D3D10:
8364                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8365                         break;
8366                 case RENDERPATH_D3D11:
8367                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8368                         break;
8369                 case RENDERPATH_GL20:
8370                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8371                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8372                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8373                         break;
8374                 case RENDERPATH_CGGL:
8375 #ifdef SUPPORTCG
8376                         CHECKCGERROR
8377                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8378                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8379                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8380 #endif
8381                         break;
8382                 case RENDERPATH_GL13:
8383                 case RENDERPATH_GL11:
8384                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8385                         break;
8386                 }
8387         }
8388 }
8389
8390 void R_ResetViewRendering2D(void)
8391 {
8392         r_viewport_t viewport;
8393         DrawQ_Finish();
8394
8395         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8396         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
8397         R_SetViewport(&viewport);
8398         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8399         GL_Color(1, 1, 1, 1);
8400         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8401         GL_BlendFunc(GL_ONE, GL_ZERO);
8402         GL_AlphaTest(false);
8403         GL_ScissorTest(false);
8404         GL_DepthMask(false);
8405         GL_DepthRange(0, 1);
8406         GL_DepthTest(false);
8407         GL_DepthFunc(GL_LEQUAL);
8408         R_EntityMatrix(&identitymatrix);
8409         R_Mesh_ResetTextureState();
8410         GL_PolygonOffset(0, 0);
8411         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8412         switch(vid.renderpath)
8413         {
8414         case RENDERPATH_GL11:
8415         case RENDERPATH_GL13:
8416         case RENDERPATH_GL20:
8417         case RENDERPATH_CGGL:
8418                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8419                 break;
8420         case RENDERPATH_D3D9:
8421         case RENDERPATH_D3D10:
8422         case RENDERPATH_D3D11:
8423                 break;
8424         }
8425         GL_CullFace(GL_NONE);
8426 }
8427
8428 void R_ResetViewRendering3D(void)
8429 {
8430         DrawQ_Finish();
8431
8432         R_SetupView(true);
8433         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8434         GL_Color(1, 1, 1, 1);
8435         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8436         GL_BlendFunc(GL_ONE, GL_ZERO);
8437         GL_AlphaTest(false);
8438         GL_ScissorTest(true);
8439         GL_DepthMask(true);
8440         GL_DepthRange(0, 1);
8441         GL_DepthTest(true);
8442         GL_DepthFunc(GL_LEQUAL);
8443         R_EntityMatrix(&identitymatrix);
8444         R_Mesh_ResetTextureState();
8445         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8446         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8447         switch(vid.renderpath)
8448         {
8449         case RENDERPATH_GL11:
8450         case RENDERPATH_GL13:
8451         case RENDERPATH_GL20:
8452         case RENDERPATH_CGGL:
8453                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8454                 break;
8455         case RENDERPATH_D3D9:
8456         case RENDERPATH_D3D10:
8457         case RENDERPATH_D3D11:
8458                 break;
8459         }
8460         GL_CullFace(r_refdef.view.cullface_back);
8461 }
8462
8463 /*
8464 ================
8465 R_RenderView_UpdateViewVectors
8466 ================
8467 */
8468 static void R_RenderView_UpdateViewVectors(void)
8469 {
8470         // break apart the view matrix into vectors for various purposes
8471         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8472         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8473         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8474         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8475         // make an inverted copy of the view matrix for tracking sprites
8476         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8477 }
8478
8479 void R_RenderScene(void);
8480 void R_RenderWaterPlanes(void);
8481
8482 static void R_Water_StartFrame(void)
8483 {
8484         int i;
8485         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8486         r_waterstate_waterplane_t *p;
8487
8488         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8489                 return;
8490
8491         switch(vid.renderpath)
8492         {
8493         case RENDERPATH_GL20:
8494         case RENDERPATH_CGGL:
8495         case RENDERPATH_D3D9:
8496         case RENDERPATH_D3D10:
8497         case RENDERPATH_D3D11:
8498                 break;
8499         case RENDERPATH_GL13:
8500         case RENDERPATH_GL11:
8501                 return;
8502         }
8503
8504         // set waterwidth and waterheight to the water resolution that will be
8505         // used (often less than the screen resolution for faster rendering)
8506         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8507         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8508
8509         // calculate desired texture sizes
8510         // can't use water if the card does not support the texture size
8511         if (!r_water.integer || r_showsurfaces.integer)
8512                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8513         else if (vid.support.arb_texture_non_power_of_two)
8514         {
8515                 texturewidth = waterwidth;
8516                 textureheight = waterheight;
8517                 camerawidth = waterwidth;
8518                 cameraheight = waterheight;
8519         }
8520         else
8521         {
8522                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8523                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8524                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8525                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8526         }
8527
8528         // allocate textures as needed
8529         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8530         {
8531                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8532                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8533                 {
8534                         if (p->texture_refraction)
8535                                 R_FreeTexture(p->texture_refraction);
8536                         p->texture_refraction = NULL;
8537                         if (p->texture_reflection)
8538                                 R_FreeTexture(p->texture_reflection);
8539                         p->texture_reflection = NULL;
8540                         if (p->texture_camera)
8541                                 R_FreeTexture(p->texture_camera);
8542                         p->texture_camera = NULL;
8543                 }
8544                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8545                 r_waterstate.texturewidth = texturewidth;
8546                 r_waterstate.textureheight = textureheight;
8547                 r_waterstate.camerawidth = camerawidth;
8548                 r_waterstate.cameraheight = cameraheight;
8549         }
8550
8551         if (r_waterstate.texturewidth)
8552         {
8553                 r_waterstate.enabled = true;
8554
8555                 // when doing a reduced render (HDR) we want to use a smaller area
8556                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8557                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8558
8559                 // set up variables that will be used in shader setup
8560                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8561                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8562                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8563                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8564         }
8565
8566         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8567         r_waterstate.numwaterplanes = 0;
8568 }
8569
8570 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8571 {
8572         int triangleindex, planeindex;
8573         const int *e;
8574         vec3_t vert[3];
8575         vec3_t normal;
8576         vec3_t center;
8577         mplane_t plane;
8578         int cam_ent;
8579         r_waterstate_waterplane_t *p;
8580         texture_t *t = R_GetCurrentTexture(surface->texture);
8581         cam_ent = t->camera_entity;
8582         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8583                 cam_ent = 0;
8584
8585         // just use the first triangle with a valid normal for any decisions
8586         VectorClear(normal);
8587         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8588         {
8589                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8590                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8591                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8592                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8593                 if (VectorLength2(normal) >= 0.001)
8594                         break;
8595         }
8596
8597         VectorCopy(normal, plane.normal);
8598         VectorNormalize(plane.normal);
8599         plane.dist = DotProduct(vert[0], plane.normal);
8600         PlaneClassify(&plane);
8601         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8602         {
8603                 // skip backfaces (except if nocullface is set)
8604                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8605                         return;
8606                 VectorNegate(plane.normal, plane.normal);
8607                 plane.dist *= -1;
8608                 PlaneClassify(&plane);
8609         }
8610
8611
8612         // find a matching plane if there is one
8613         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8614                 if(p->camera_entity == t->camera_entity)
8615                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8616                                 break;
8617         if (planeindex >= r_waterstate.maxwaterplanes)
8618                 return; // nothing we can do, out of planes
8619
8620         // if this triangle does not fit any known plane rendered this frame, add one
8621         if (planeindex >= r_waterstate.numwaterplanes)
8622         {
8623                 // store the new plane
8624                 r_waterstate.numwaterplanes++;
8625                 p->plane = plane;
8626                 // clear materialflags and pvs
8627                 p->materialflags = 0;
8628                 p->pvsvalid = false;
8629                 p->camera_entity = t->camera_entity;
8630         }
8631         // merge this surface's materialflags into the waterplane
8632         p->materialflags |= t->currentmaterialflags;
8633         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8634         {
8635                 // merge this surface's PVS into the waterplane
8636                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8637                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8638                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8639                 {
8640                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8641                         p->pvsvalid = true;
8642                 }
8643         }
8644 }
8645
8646 static void R_Water_ProcessPlanes(void)
8647 {
8648         r_refdef_view_t originalview;
8649         r_refdef_view_t myview;
8650         int planeindex;
8651         r_waterstate_waterplane_t *p;
8652         vec3_t visorigin;
8653
8654         originalview = r_refdef.view;
8655
8656         // make sure enough textures are allocated
8657         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8658         {
8659                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8660                 {
8661                         if (!p->texture_refraction)
8662                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8663                         if (!p->texture_refraction)
8664                                 goto error;
8665                 }
8666                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8667                 {
8668                         if (!p->texture_camera)
8669                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8670                         if (!p->texture_camera)
8671                                 goto error;
8672                 }
8673
8674                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8675                 {
8676                         if (!p->texture_reflection)
8677                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8678                         if (!p->texture_reflection)
8679                                 goto error;
8680                 }
8681         }
8682
8683         // render views
8684         r_refdef.view = originalview;
8685         r_refdef.view.showdebug = false;
8686         r_refdef.view.width = r_waterstate.waterwidth;
8687         r_refdef.view.height = r_waterstate.waterheight;
8688         r_refdef.view.useclipplane = true;
8689         myview = r_refdef.view;
8690         r_waterstate.renderingscene = true;
8691         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8692         {
8693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8694                 {
8695                         r_refdef.view = myview;
8696                         // render reflected scene and copy into texture
8697                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8698                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8699                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8700                         r_refdef.view.clipplane = p->plane;
8701                         // reverse the cullface settings for this render
8702                         r_refdef.view.cullface_front = GL_FRONT;
8703                         r_refdef.view.cullface_back = GL_BACK;
8704                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8705                         {
8706                                 r_refdef.view.usecustompvs = true;
8707                                 if (p->pvsvalid)
8708                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8709                                 else
8710                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8711                         }
8712
8713                         R_ResetViewRendering3D();
8714                         R_ClearScreen(r_refdef.fogenabled);
8715                         R_View_Update();
8716                         R_RenderScene();
8717
8718                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8719                 }
8720
8721                 // render the normal view scene and copy into texture
8722                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
8723                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8724                 {
8725                         r_waterstate.renderingrefraction = true;
8726                         r_refdef.view = myview;
8727
8728                         r_refdef.view.clipplane = p->plane;
8729                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8730                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8731
8732                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8733                         {
8734                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8735                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8736                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8737                                 R_RenderView_UpdateViewVectors();
8738                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8739                                 {
8740                                         r_refdef.view.usecustompvs = true;
8741                                         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);
8742                                 }
8743                         }
8744
8745                         PlaneClassify(&r_refdef.view.clipplane);
8746
8747                         R_ResetViewRendering3D();
8748                         R_ClearScreen(r_refdef.fogenabled);
8749                         R_View_Update();
8750                         R_RenderScene();
8751
8752                         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);
8753                         r_waterstate.renderingrefraction = false;
8754                 }
8755                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8756                 {
8757                         r_refdef.view = myview;
8758
8759                         r_refdef.view.clipplane = p->plane;
8760                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8761                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8762
8763                         r_refdef.view.width = r_waterstate.camerawidth;
8764                         r_refdef.view.height = r_waterstate.cameraheight;
8765                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8766                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8767
8768                         if(p->camera_entity)
8769                         {
8770                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8771                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8772                         }
8773
8774                         // reverse the cullface settings for this render
8775                         r_refdef.view.cullface_front = GL_FRONT;
8776                         r_refdef.view.cullface_back = GL_BACK;
8777                         // also reverse the view matrix
8778                         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
8779                         R_RenderView_UpdateViewVectors();
8780                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8781                         {
8782                                 r_refdef.view.usecustompvs = true;
8783                                 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);
8784                         }
8785                         
8786                         // camera needs no clipplane
8787                         r_refdef.view.useclipplane = false;
8788
8789                         PlaneClassify(&r_refdef.view.clipplane);
8790
8791                         R_ResetViewRendering3D();
8792                         R_ClearScreen(r_refdef.fogenabled);
8793                         R_View_Update();
8794                         R_RenderScene();
8795
8796                         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);
8797                         r_waterstate.renderingrefraction = false;
8798                 }
8799
8800         }
8801         r_waterstate.renderingscene = false;
8802         r_refdef.view = originalview;
8803         R_ResetViewRendering3D();
8804         R_ClearScreen(r_refdef.fogenabled);
8805         R_View_Update();
8806         return;
8807 error:
8808         r_refdef.view = originalview;
8809         r_waterstate.renderingscene = false;
8810         Cvar_SetValueQuick(&r_water, 0);
8811         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8812         return;
8813 }
8814
8815 void R_Bloom_StartFrame(void)
8816 {
8817         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8818
8819         switch(vid.renderpath)
8820         {
8821         case RENDERPATH_GL20:
8822         case RENDERPATH_CGGL:
8823         case RENDERPATH_D3D9:
8824         case RENDERPATH_D3D10:
8825         case RENDERPATH_D3D11:
8826                 break;
8827         case RENDERPATH_GL13:
8828         case RENDERPATH_GL11:
8829                 return;
8830         }
8831
8832         // set bloomwidth and bloomheight to the bloom resolution that will be
8833         // used (often less than the screen resolution for faster rendering)
8834         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8835         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8836         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8837         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8838         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8839
8840         // calculate desired texture sizes
8841         if (vid.support.arb_texture_non_power_of_two)
8842         {
8843                 screentexturewidth = r_refdef.view.width;
8844                 screentextureheight = r_refdef.view.height;
8845                 bloomtexturewidth = r_bloomstate.bloomwidth;
8846                 bloomtextureheight = r_bloomstate.bloomheight;
8847         }
8848         else
8849         {
8850                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8851                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8852                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8853                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8854         }
8855
8856         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))
8857         {
8858                 Cvar_SetValueQuick(&r_hdr, 0);
8859                 Cvar_SetValueQuick(&r_bloom, 0);
8860                 Cvar_SetValueQuick(&r_motionblur, 0);
8861                 Cvar_SetValueQuick(&r_damageblur, 0);
8862         }
8863
8864         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)))
8865                 screentexturewidth = screentextureheight = 0;
8866         if (!r_hdr.integer && !r_bloom.integer)
8867                 bloomtexturewidth = bloomtextureheight = 0;
8868
8869         // allocate textures as needed
8870         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8871         {
8872                 if (r_bloomstate.texture_screen)
8873                         R_FreeTexture(r_bloomstate.texture_screen);
8874                 r_bloomstate.texture_screen = NULL;
8875                 r_bloomstate.screentexturewidth = screentexturewidth;
8876                 r_bloomstate.screentextureheight = screentextureheight;
8877                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8878                         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);
8879         }
8880         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8881         {
8882                 if (r_bloomstate.texture_bloom)
8883                         R_FreeTexture(r_bloomstate.texture_bloom);
8884                 r_bloomstate.texture_bloom = NULL;
8885                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8886                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8887                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8888                         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);
8889         }
8890
8891         // when doing a reduced render (HDR) we want to use a smaller area
8892         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8893         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8894         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8895         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8896         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8897
8898         // set up a texcoord array for the full resolution screen image
8899         // (we have to keep this around to copy back during final render)
8900         r_bloomstate.screentexcoord2f[0] = 0;
8901         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8902         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8903         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8904         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8905         r_bloomstate.screentexcoord2f[5] = 0;
8906         r_bloomstate.screentexcoord2f[6] = 0;
8907         r_bloomstate.screentexcoord2f[7] = 0;
8908
8909         // set up a texcoord array for the reduced resolution bloom image
8910         // (which will be additive blended over the screen image)
8911         r_bloomstate.bloomtexcoord2f[0] = 0;
8912         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8913         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8914         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8915         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8916         r_bloomstate.bloomtexcoord2f[5] = 0;
8917         r_bloomstate.bloomtexcoord2f[6] = 0;
8918         r_bloomstate.bloomtexcoord2f[7] = 0;
8919
8920         switch(vid.renderpath)
8921         {
8922         case RENDERPATH_GL11:
8923         case RENDERPATH_GL13:
8924         case RENDERPATH_GL20:
8925         case RENDERPATH_CGGL:
8926                 break;
8927         case RENDERPATH_D3D9:
8928         case RENDERPATH_D3D10:
8929         case RENDERPATH_D3D11:
8930                 {
8931                         int i;
8932                         for (i = 0;i < 4;i++)
8933                         {
8934                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8935                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8936                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8937                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8938                         }
8939                 }
8940                 break;
8941         }
8942
8943         if (r_hdr.integer || r_bloom.integer)
8944         {
8945                 r_bloomstate.enabled = true;
8946                 r_bloomstate.hdr = r_hdr.integer != 0;
8947         }
8948
8949         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);
8950 }
8951
8952 void R_Bloom_CopyBloomTexture(float colorscale)
8953 {
8954         r_refdef.stats.bloom++;
8955
8956         // scale down screen texture to the bloom texture size
8957         CHECKGLERROR
8958         R_SetViewport(&r_bloomstate.viewport);
8959         GL_BlendFunc(GL_ONE, GL_ZERO);
8960         GL_Color(colorscale, colorscale, colorscale, 1);
8961         // 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...
8962         switch(vid.renderpath)
8963         {
8964         case RENDERPATH_GL11:
8965         case RENDERPATH_GL13:
8966         case RENDERPATH_GL20:
8967         case RENDERPATH_CGGL:
8968                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8969                 break;
8970         case RENDERPATH_D3D9:
8971         case RENDERPATH_D3D10:
8972         case RENDERPATH_D3D11:
8973                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8974                 break;
8975         }
8976         // TODO: do boxfilter scale-down in shader?
8977         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8978         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8979         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8980
8981         // we now have a bloom image in the framebuffer
8982         // copy it into the bloom image texture for later processing
8983         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);
8984         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8985 }
8986
8987 void R_Bloom_CopyHDRTexture(void)
8988 {
8989         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);
8990         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8991 }
8992
8993 void R_Bloom_MakeTexture(void)
8994 {
8995         int x, range, dir;
8996         float xoffset, yoffset, r, brighten;
8997
8998         r_refdef.stats.bloom++;
8999
9000         R_ResetViewRendering2D();
9001
9002         // we have a bloom image in the framebuffer
9003         CHECKGLERROR
9004         R_SetViewport(&r_bloomstate.viewport);
9005
9006         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9007         {
9008                 x *= 2;
9009                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9010                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9011                 GL_Color(r,r,r,1);
9012                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9013                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9014                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9015                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9016
9017                 // copy the vertically blurred bloom view to a texture
9018                 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);
9019                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9020         }
9021
9022         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9023         brighten = r_bloom_brighten.value;
9024         if (r_hdr.integer)
9025                 brighten *= r_hdr_range.value;
9026         brighten = sqrt(brighten);
9027         if(range >= 1)
9028                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9029         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9030
9031         for (dir = 0;dir < 2;dir++)
9032         {
9033                 // blend on at multiple vertical offsets to achieve a vertical blur
9034                 // TODO: do offset blends using GLSL
9035                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9036                 GL_BlendFunc(GL_ONE, GL_ZERO);
9037                 for (x = -range;x <= range;x++)
9038                 {
9039                         if (!dir){xoffset = 0;yoffset = x;}
9040                         else {xoffset = x;yoffset = 0;}
9041                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9042                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9043                         // compute a texcoord array with the specified x and y offset
9044                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9045                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9046                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9047                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9048                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9049                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9050                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9051                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9052                         // this r value looks like a 'dot' particle, fading sharply to
9053                         // black at the edges
9054                         // (probably not realistic but looks good enough)
9055                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9056                         //r = brighten/(range*2+1);
9057                         r = brighten / (range * 2 + 1);
9058                         if(range >= 1)
9059                                 r *= (1 - x*x/(float)(range*range));
9060                         GL_Color(r, r, r, 1);
9061                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9062                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9063                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9064                         GL_BlendFunc(GL_ONE, GL_ONE);
9065                 }
9066
9067                 // copy the vertically blurred bloom view to a texture
9068                 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);
9069                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9070         }
9071 }
9072
9073 void R_HDR_RenderBloomTexture(void)
9074 {
9075         int oldwidth, oldheight;
9076         float oldcolorscale;
9077
9078         oldcolorscale = r_refdef.view.colorscale;
9079         oldwidth = r_refdef.view.width;
9080         oldheight = r_refdef.view.height;
9081         r_refdef.view.width = r_bloomstate.bloomwidth;
9082         r_refdef.view.height = r_bloomstate.bloomheight;
9083
9084         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9085         // TODO: add exposure compensation features
9086         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9087
9088         r_refdef.view.showdebug = false;
9089         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9090
9091         R_ResetViewRendering3D();
9092
9093         R_ClearScreen(r_refdef.fogenabled);
9094         if (r_timereport_active)
9095                 R_TimeReport("HDRclear");
9096
9097         R_View_Update();
9098         if (r_timereport_active)
9099                 R_TimeReport("visibility");
9100
9101         // only do secondary renders with HDR if r_hdr is 2 or higher
9102         r_waterstate.numwaterplanes = 0;
9103         if (r_waterstate.enabled && r_hdr.integer >= 2)
9104                 R_RenderWaterPlanes();
9105
9106         r_refdef.view.showdebug = true;
9107         R_RenderScene();
9108         r_waterstate.numwaterplanes = 0;
9109
9110         R_ResetViewRendering2D();
9111
9112         R_Bloom_CopyHDRTexture();
9113         R_Bloom_MakeTexture();
9114
9115         // restore the view settings
9116         r_refdef.view.width = oldwidth;
9117         r_refdef.view.height = oldheight;
9118         r_refdef.view.colorscale = oldcolorscale;
9119
9120         R_ResetViewRendering3D();
9121
9122         R_ClearScreen(r_refdef.fogenabled);
9123         if (r_timereport_active)
9124                 R_TimeReport("viewclear");
9125 }
9126
9127 static void R_BlendView(void)
9128 {
9129         unsigned int permutation;
9130         float uservecs[4][4];
9131
9132         switch (vid.renderpath)
9133         {
9134         case RENDERPATH_GL20:
9135         case RENDERPATH_CGGL:
9136         case RENDERPATH_D3D9:
9137         case RENDERPATH_D3D10:
9138         case RENDERPATH_D3D11:
9139                 permutation =
9140                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9141                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9142                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9143                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9144                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9145
9146                 if (r_bloomstate.texture_screen)
9147                 {
9148                         // make sure the buffer is available
9149                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9150
9151                         R_ResetViewRendering2D();
9152
9153                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9154                         {
9155                                 // declare variables
9156                                 float speed;
9157                                 static float avgspeed;
9158
9159                                 speed = VectorLength(cl.movement_velocity);
9160
9161                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9162                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9163
9164                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9165                                 speed = bound(0, speed, 1);
9166                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9167
9168                                 // calculate values into a standard alpha
9169                                 cl.motionbluralpha = 1 - exp(-
9170                                                 (
9171                                                  (r_motionblur.value * speed / 80)
9172                                                  +
9173                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9174                                                 )
9175                                                 /
9176                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9177                                            );
9178
9179                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9180                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9181                                 // apply the blur
9182                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9183                                 {
9184                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9185                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9186                                         switch(vid.renderpath)
9187                                         {
9188                                         case RENDERPATH_GL11:
9189                                         case RENDERPATH_GL13:
9190                                         case RENDERPATH_GL20:
9191                                         case RENDERPATH_CGGL:
9192                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9193                                                 break;
9194                                         case RENDERPATH_D3D9:
9195                                         case RENDERPATH_D3D10:
9196                                         case RENDERPATH_D3D11:
9197                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9198                                                 break;
9199                                         }
9200                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9201                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9202                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9203                                 }
9204                         }
9205
9206                         // copy view into the screen texture
9207                         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);
9208                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9209                 }
9210                 else if (!r_bloomstate.texture_bloom)
9211                 {
9212                         // we may still have to do view tint...
9213                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9214                         {
9215                                 // apply a color tint to the whole view
9216                                 R_ResetViewRendering2D();
9217                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9218                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9219                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9220                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9221                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9222                         }
9223                         break; // no screen processing, no bloom, skip it
9224                 }
9225
9226                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9227                 {
9228                         // render simple bloom effect
9229                         // copy the screen and shrink it and darken it for the bloom process
9230                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9231                         // make the bloom texture
9232                         R_Bloom_MakeTexture();
9233                 }
9234
9235 #if _MSC_VER >= 1400
9236 #define sscanf sscanf_s
9237 #endif
9238                 memset(uservecs, 0, sizeof(uservecs));
9239                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9240                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9241                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9242                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9243
9244                 R_ResetViewRendering2D();
9245                 GL_Color(1, 1, 1, 1);
9246                 GL_BlendFunc(GL_ONE, GL_ZERO);
9247
9248                 switch(vid.renderpath)
9249                 {
9250                 case RENDERPATH_GL20:
9251                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9252                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9253                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9254                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9255                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9256                         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]);
9257                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9258                         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]);
9259                         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]);
9260                         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]);
9261                         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]);
9262                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9263                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9264                         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);
9265                         break;
9266                 case RENDERPATH_CGGL:
9267 #ifdef SUPPORTCG
9268                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9269                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9270                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9271                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9272                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9273                         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
9274                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9275                         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
9276                         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
9277                         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
9278                         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
9279                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9280                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9281                         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);
9282 #endif
9283                         break;
9284                 case RENDERPATH_D3D9:
9285 #ifdef SUPPORTD3D
9286                         // 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...
9287                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9288                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9289                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9290                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9291                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9292                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9293                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9294                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9295                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9296                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9297                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9298                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9299                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9300                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9301 #endif
9302                         break;
9303                 case RENDERPATH_D3D10:
9304                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9305                         break;
9306                 case RENDERPATH_D3D11:
9307                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9308                         break;
9309                 default:
9310                         break;
9311                 }
9312                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9313                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9314                 break;
9315         case RENDERPATH_GL13:
9316         case RENDERPATH_GL11:
9317                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9318                 {
9319                         // apply a color tint to the whole view
9320                         R_ResetViewRendering2D();
9321                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9322                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9323                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9324                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9325                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9326                 }
9327                 break;
9328         }
9329 }
9330
9331 matrix4x4_t r_waterscrollmatrix;
9332
9333 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9334 {
9335         if (r_refdef.fog_density)
9336         {
9337                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9338                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9339                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9340
9341                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9342                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9343                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9344                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9345
9346                 {
9347                         vec3_t fogvec;
9348                         VectorCopy(r_refdef.fogcolor, fogvec);
9349                         //   color.rgb *= ContrastBoost * SceneBrightness;
9350                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9351                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9352                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9353                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9354                 }
9355         }
9356 }
9357
9358 void R_UpdateVariables(void)
9359 {
9360         R_Textures_Frame();
9361
9362         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9363
9364         r_refdef.farclip = r_farclip_base.value;
9365         if (r_refdef.scene.worldmodel)
9366                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9367         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9368
9369         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9370                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9371         r_refdef.polygonfactor = 0;
9372         r_refdef.polygonoffset = 0;
9373         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9374         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9375
9376         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9377         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9378         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9379         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9380         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9381         if (r_showsurfaces.integer)
9382         {
9383                 r_refdef.scene.rtworld = false;
9384                 r_refdef.scene.rtworldshadows = false;
9385                 r_refdef.scene.rtdlight = false;
9386                 r_refdef.scene.rtdlightshadows = false;
9387                 r_refdef.lightmapintensity = 0;
9388         }
9389
9390         if (gamemode == GAME_NEHAHRA)
9391         {
9392                 if (gl_fogenable.integer)
9393                 {
9394                         r_refdef.oldgl_fogenable = true;
9395                         r_refdef.fog_density = gl_fogdensity.value;
9396                         r_refdef.fog_red = gl_fogred.value;
9397                         r_refdef.fog_green = gl_foggreen.value;
9398                         r_refdef.fog_blue = gl_fogblue.value;
9399                         r_refdef.fog_alpha = 1;
9400                         r_refdef.fog_start = 0;
9401                         r_refdef.fog_end = gl_skyclip.value;
9402                         r_refdef.fog_height = 1<<30;
9403                         r_refdef.fog_fadedepth = 128;
9404                 }
9405                 else if (r_refdef.oldgl_fogenable)
9406                 {
9407                         r_refdef.oldgl_fogenable = false;
9408                         r_refdef.fog_density = 0;
9409                         r_refdef.fog_red = 0;
9410                         r_refdef.fog_green = 0;
9411                         r_refdef.fog_blue = 0;
9412                         r_refdef.fog_alpha = 0;
9413                         r_refdef.fog_start = 0;
9414                         r_refdef.fog_end = 0;
9415                         r_refdef.fog_height = 1<<30;
9416                         r_refdef.fog_fadedepth = 128;
9417                 }
9418         }
9419
9420         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9421         r_refdef.fog_start = max(0, r_refdef.fog_start);
9422         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9423
9424         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9425
9426         if (r_refdef.fog_density && r_drawfog.integer)
9427         {
9428                 r_refdef.fogenabled = true;
9429                 // this is the point where the fog reaches 0.9986 alpha, which we
9430                 // consider a good enough cutoff point for the texture
9431                 // (0.9986 * 256 == 255.6)
9432                 if (r_fog_exp2.integer)
9433                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9434                 else
9435                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9436                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9437                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9438                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9439                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9440                         R_BuildFogHeightTexture();
9441                 // fog color was already set
9442                 // update the fog texture
9443                 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)
9444                         R_BuildFogTexture();
9445                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9446                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9447         }
9448         else
9449                 r_refdef.fogenabled = false;
9450
9451         switch(vid.renderpath)
9452         {
9453         case RENDERPATH_GL20:
9454         case RENDERPATH_CGGL:
9455         case RENDERPATH_D3D9:
9456         case RENDERPATH_D3D10:
9457         case RENDERPATH_D3D11:
9458                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9459                 {
9460                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9461                         {
9462                                 // build GLSL gamma texture
9463 #define RAMPWIDTH 256
9464                                 unsigned short ramp[RAMPWIDTH * 3];
9465                                 unsigned char rampbgr[RAMPWIDTH][4];
9466                                 int i;
9467
9468                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9469
9470                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9471                                 for(i = 0; i < RAMPWIDTH; ++i)
9472                                 {
9473                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9474                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9475                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9476                                         rampbgr[i][3] = 0;
9477                                 }
9478                                 if (r_texture_gammaramps)
9479                                 {
9480                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9481                                 }
9482                                 else
9483                                 {
9484                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9485                                 }
9486                         }
9487                 }
9488                 else
9489                 {
9490                         // remove GLSL gamma texture
9491                 }
9492                 break;
9493         case RENDERPATH_GL13:
9494         case RENDERPATH_GL11:
9495                 break;
9496         }
9497 }
9498
9499 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9500 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9501 /*
9502 ================
9503 R_SelectScene
9504 ================
9505 */
9506 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9507         if( scenetype != r_currentscenetype ) {
9508                 // store the old scenetype
9509                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9510                 r_currentscenetype = scenetype;
9511                 // move in the new scene
9512                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9513         }
9514 }
9515
9516 /*
9517 ================
9518 R_GetScenePointer
9519 ================
9520 */
9521 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9522 {
9523         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9524         if( scenetype == r_currentscenetype ) {
9525                 return &r_refdef.scene;
9526         } else {
9527                 return &r_scenes_store[ scenetype ];
9528         }
9529 }
9530
9531 /*
9532 ================
9533 R_RenderView
9534 ================
9535 */
9536 void R_RenderView(void)
9537 {
9538         if (r_timereport_active)
9539                 R_TimeReport("start");
9540         r_textureframe++; // used only by R_GetCurrentTexture
9541         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9542
9543         if (!r_drawentities.integer)
9544                 r_refdef.scene.numentities = 0;
9545
9546         R_AnimCache_ClearCache();
9547         R_FrameData_NewFrame();
9548
9549         if (r_refdef.view.isoverlay)
9550         {
9551                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9552                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9553                 R_TimeReport("depthclear");
9554
9555                 r_refdef.view.showdebug = false;
9556
9557                 r_waterstate.enabled = false;
9558                 r_waterstate.numwaterplanes = 0;
9559
9560                 R_RenderScene();
9561
9562                 CHECKGLERROR
9563                 return;
9564         }
9565
9566         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9567                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9568
9569         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9570
9571         R_RenderView_UpdateViewVectors();
9572
9573         R_Shadow_UpdateWorldLightSelection();
9574
9575         R_Bloom_StartFrame();
9576         R_Water_StartFrame();
9577
9578         CHECKGLERROR
9579         if (r_timereport_active)
9580                 R_TimeReport("viewsetup");
9581
9582         R_ResetViewRendering3D();
9583
9584         if (r_refdef.view.clear || r_refdef.fogenabled)
9585         {
9586                 R_ClearScreen(r_refdef.fogenabled);
9587                 if (r_timereport_active)
9588                         R_TimeReport("viewclear");
9589         }
9590         r_refdef.view.clear = true;
9591
9592         // this produces a bloom texture to be used in R_BlendView() later
9593         if (r_hdr.integer && r_bloomstate.bloomwidth)
9594         {
9595                 R_HDR_RenderBloomTexture();
9596                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9597                 r_textureframe++; // used only by R_GetCurrentTexture
9598         }
9599
9600         r_refdef.view.showdebug = true;
9601
9602         R_View_Update();
9603         if (r_timereport_active)
9604                 R_TimeReport("visibility");
9605
9606         r_waterstate.numwaterplanes = 0;
9607         if (r_waterstate.enabled)
9608                 R_RenderWaterPlanes();
9609
9610         R_RenderScene();
9611         r_waterstate.numwaterplanes = 0;
9612
9613         R_BlendView();
9614         if (r_timereport_active)
9615                 R_TimeReport("blendview");
9616
9617         GL_Scissor(0, 0, vid.width, vid.height);
9618         GL_ScissorTest(false);
9619         CHECKGLERROR
9620 }
9621
9622 void R_RenderWaterPlanes(void)
9623 {
9624         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9625         {
9626                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9627                 if (r_timereport_active)
9628                         R_TimeReport("waterworld");
9629         }
9630
9631         // don't let sound skip if going slow
9632         if (r_refdef.scene.extraupdate)
9633                 S_ExtraUpdate ();
9634
9635         R_DrawModelsAddWaterPlanes();
9636         if (r_timereport_active)
9637                 R_TimeReport("watermodels");
9638
9639         if (r_waterstate.numwaterplanes)
9640         {
9641                 R_Water_ProcessPlanes();
9642                 if (r_timereport_active)
9643                         R_TimeReport("waterscenes");
9644         }
9645 }
9646
9647 extern void R_DrawLightningBeams (void);
9648 extern void VM_CL_AddPolygonsToMeshQueue (void);
9649 extern void R_DrawPortals (void);
9650 extern cvar_t cl_locs_show;
9651 static void R_DrawLocs(void);
9652 static void R_DrawEntityBBoxes(void);
9653 static void R_DrawModelDecals(void);
9654 extern void R_DrawModelShadows(void);
9655 extern void R_DrawModelShadowMaps(void);
9656 extern cvar_t cl_decals_newsystem;
9657 extern qboolean r_shadow_usingdeferredprepass;
9658 void R_RenderScene(void)
9659 {
9660         qboolean shadowmapping = false;
9661
9662         if (r_timereport_active)
9663                 R_TimeReport("beginscene");
9664
9665         r_refdef.stats.renders++;
9666
9667         R_UpdateFogColor();
9668
9669         // don't let sound skip if going slow
9670         if (r_refdef.scene.extraupdate)
9671                 S_ExtraUpdate ();
9672
9673         R_MeshQueue_BeginScene();
9674
9675         R_SkyStartFrame();
9676
9677         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);
9678
9679         if (r_timereport_active)
9680                 R_TimeReport("skystartframe");
9681
9682         if (cl.csqc_vidvars.drawworld)
9683         {
9684                 // don't let sound skip if going slow
9685                 if (r_refdef.scene.extraupdate)
9686                         S_ExtraUpdate ();
9687
9688                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9689                 {
9690                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9691                         if (r_timereport_active)
9692                                 R_TimeReport("worldsky");
9693                 }
9694
9695                 if (R_DrawBrushModelsSky() && r_timereport_active)
9696                         R_TimeReport("bmodelsky");
9697
9698                 if (skyrendermasked && skyrenderlater)
9699                 {
9700                         // we have to force off the water clipping plane while rendering sky
9701                         R_SetupView(false);
9702                         R_Sky();
9703                         R_SetupView(true);
9704                         if (r_timereport_active)
9705                                 R_TimeReport("sky");
9706                 }
9707         }
9708
9709         R_AnimCache_CacheVisibleEntities();
9710         if (r_timereport_active)
9711                 R_TimeReport("animation");
9712
9713         R_Shadow_PrepareLights();
9714         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9715                 R_Shadow_PrepareModelShadows();
9716         if (r_timereport_active)
9717                 R_TimeReport("preparelights");
9718
9719         if (R_Shadow_ShadowMappingEnabled())
9720                 shadowmapping = true;
9721
9722         if (r_shadow_usingdeferredprepass)
9723                 R_Shadow_DrawPrepass();
9724
9725         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9726         {
9727                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9728                 if (r_timereport_active)
9729                         R_TimeReport("worlddepth");
9730         }
9731         if (r_depthfirst.integer >= 2)
9732         {
9733                 R_DrawModelsDepth();
9734                 if (r_timereport_active)
9735                         R_TimeReport("modeldepth");
9736         }
9737
9738         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9739         {
9740                 R_DrawModelShadowMaps();
9741                 R_ResetViewRendering3D();
9742                 // don't let sound skip if going slow
9743                 if (r_refdef.scene.extraupdate)
9744                         S_ExtraUpdate ();
9745         }
9746
9747         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9748         {
9749                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9750                 if (r_timereport_active)
9751                         R_TimeReport("world");
9752         }
9753
9754         // don't let sound skip if going slow
9755         if (r_refdef.scene.extraupdate)
9756                 S_ExtraUpdate ();
9757
9758         R_DrawModels();
9759         if (r_timereport_active)
9760                 R_TimeReport("models");
9761
9762         // don't let sound skip if going slow
9763         if (r_refdef.scene.extraupdate)
9764                 S_ExtraUpdate ();
9765
9766         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9767         {
9768                 R_DrawModelShadows();
9769                 R_ResetViewRendering3D();
9770                 // don't let sound skip if going slow
9771                 if (r_refdef.scene.extraupdate)
9772                         S_ExtraUpdate ();
9773         }
9774
9775         if (!r_shadow_usingdeferredprepass)
9776         {
9777                 R_Shadow_DrawLights();
9778                 if (r_timereport_active)
9779                         R_TimeReport("rtlights");
9780         }
9781
9782         // don't let sound skip if going slow
9783         if (r_refdef.scene.extraupdate)
9784                 S_ExtraUpdate ();
9785
9786         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9787         {
9788                 R_DrawModelShadows();
9789                 R_ResetViewRendering3D();
9790                 // don't let sound skip if going slow
9791                 if (r_refdef.scene.extraupdate)
9792                         S_ExtraUpdate ();
9793         }
9794
9795         if (cl.csqc_vidvars.drawworld)
9796         {
9797                 if (cl_decals_newsystem.integer)
9798                 {
9799                         R_DrawModelDecals();
9800                         if (r_timereport_active)
9801                                 R_TimeReport("modeldecals");
9802                 }
9803                 else
9804                 {
9805                         R_DrawDecals();
9806                         if (r_timereport_active)
9807                                 R_TimeReport("decals");
9808                 }
9809
9810                 R_DrawParticles();
9811                 if (r_timereport_active)
9812                         R_TimeReport("particles");
9813
9814                 R_DrawExplosions();
9815                 if (r_timereport_active)
9816                         R_TimeReport("explosions");
9817
9818                 R_DrawLightningBeams();
9819                 if (r_timereport_active)
9820                         R_TimeReport("lightning");
9821         }
9822
9823         VM_CL_AddPolygonsToMeshQueue();
9824
9825         if (r_refdef.view.showdebug)
9826         {
9827                 if (cl_locs_show.integer)
9828                 {
9829                         R_DrawLocs();
9830                         if (r_timereport_active)
9831                                 R_TimeReport("showlocs");
9832                 }
9833
9834                 if (r_drawportals.integer)
9835                 {
9836                         R_DrawPortals();
9837                         if (r_timereport_active)
9838                                 R_TimeReport("portals");
9839                 }
9840
9841                 if (r_showbboxes.value > 0)
9842                 {
9843                         R_DrawEntityBBoxes();
9844                         if (r_timereport_active)
9845                                 R_TimeReport("bboxes");
9846                 }
9847         }
9848
9849         R_MeshQueue_RenderTransparent();
9850         if (r_timereport_active)
9851                 R_TimeReport("drawtrans");
9852
9853         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))
9854         {
9855                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9856                 if (r_timereport_active)
9857                         R_TimeReport("worlddebug");
9858                 R_DrawModelsDebug();
9859                 if (r_timereport_active)
9860                         R_TimeReport("modeldebug");
9861         }
9862
9863         if (cl.csqc_vidvars.drawworld)
9864         {
9865                 R_Shadow_DrawCoronas();
9866                 if (r_timereport_active)
9867                         R_TimeReport("coronas");
9868         }
9869
9870         // don't let sound skip if going slow
9871         if (r_refdef.scene.extraupdate)
9872                 S_ExtraUpdate ();
9873
9874         R_ResetViewRendering2D();
9875 }
9876
9877 static const unsigned short bboxelements[36] =
9878 {
9879         5, 1, 3, 5, 3, 7,
9880         6, 2, 0, 6, 0, 4,
9881         7, 3, 2, 7, 2, 6,
9882         4, 0, 1, 4, 1, 5,
9883         4, 5, 7, 4, 7, 6,
9884         1, 0, 2, 1, 2, 3,
9885 };
9886
9887 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9888 {
9889         int i;
9890         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9891
9892         RSurf_ActiveWorldEntity();
9893
9894         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9895         GL_DepthMask(false);
9896         GL_DepthRange(0, 1);
9897         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9898         R_Mesh_ResetTextureState();
9899
9900         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9901         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9902         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9903         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9904         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9905         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9906         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9907         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9908         R_FillColors(color4f, 8, cr, cg, cb, ca);
9909         if (r_refdef.fogenabled)
9910         {
9911                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9912                 {
9913                         f1 = RSurf_FogVertex(v);
9914                         f2 = 1 - f1;
9915                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9916                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9917                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9918                 }
9919         }
9920         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9921         R_Mesh_ResetTextureState();
9922         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9923         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9924 }
9925
9926 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9927 {
9928         int i;
9929         float color[4];
9930         prvm_edict_t *edict;
9931         prvm_prog_t *prog_save = prog;
9932
9933         // this function draws bounding boxes of server entities
9934         if (!sv.active)
9935                 return;
9936
9937         GL_CullFace(GL_NONE);
9938         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9939
9940         prog = 0;
9941         SV_VM_Begin();
9942         for (i = 0;i < numsurfaces;i++)
9943         {
9944                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9945                 switch ((int)edict->fields.server->solid)
9946                 {
9947                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9948                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9949                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9950                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9951                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9952                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9953                 }
9954                 color[3] *= r_showbboxes.value;
9955                 color[3] = bound(0, color[3], 1);
9956                 GL_DepthTest(!r_showdisabledepthtest.integer);
9957                 GL_CullFace(r_refdef.view.cullface_front);
9958                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9959         }
9960         SV_VM_End();
9961         prog = prog_save;
9962 }
9963
9964 static void R_DrawEntityBBoxes(void)
9965 {
9966         int i;
9967         prvm_edict_t *edict;
9968         vec3_t center;
9969         prvm_prog_t *prog_save = prog;
9970
9971         // this function draws bounding boxes of server entities
9972         if (!sv.active)
9973                 return;
9974
9975         prog = 0;
9976         SV_VM_Begin();
9977         for (i = 0;i < prog->num_edicts;i++)
9978         {
9979                 edict = PRVM_EDICT_NUM(i);
9980                 if (edict->priv.server->free)
9981                         continue;
9982                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9983                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9984                         continue;
9985                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9986                         continue;
9987                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9988                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9989         }
9990         SV_VM_End();
9991         prog = prog_save;
9992 }
9993
9994 static const int nomodelelement3i[24] =
9995 {
9996         5, 2, 0,
9997         5, 1, 2,
9998         5, 0, 3,
9999         5, 3, 1,
10000         0, 2, 4,
10001         2, 1, 4,
10002         3, 0, 4,
10003         1, 3, 4
10004 };
10005
10006 static const unsigned short nomodelelement3s[24] =
10007 {
10008         5, 2, 0,
10009         5, 1, 2,
10010         5, 0, 3,
10011         5, 3, 1,
10012         0, 2, 4,
10013         2, 1, 4,
10014         3, 0, 4,
10015         1, 3, 4
10016 };
10017
10018 static const float nomodelvertex3f[6*3] =
10019 {
10020         -16,   0,   0,
10021          16,   0,   0,
10022           0, -16,   0,
10023           0,  16,   0,
10024           0,   0, -16,
10025           0,   0,  16
10026 };
10027
10028 static const float nomodelcolor4f[6*4] =
10029 {
10030         0.0f, 0.0f, 0.5f, 1.0f,
10031         0.0f, 0.0f, 0.5f, 1.0f,
10032         0.0f, 0.5f, 0.0f, 1.0f,
10033         0.0f, 0.5f, 0.0f, 1.0f,
10034         0.5f, 0.0f, 0.0f, 1.0f,
10035         0.5f, 0.0f, 0.0f, 1.0f
10036 };
10037
10038 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10039 {
10040         int i;
10041         float f1, f2, *c;
10042         float color4f[6*4];
10043
10044         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);
10045
10046         // this is only called once per entity so numsurfaces is always 1, and
10047         // surfacelist is always {0}, so this code does not handle batches
10048
10049         if (rsurface.ent_flags & RENDER_ADDITIVE)
10050         {
10051                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10052                 GL_DepthMask(false);
10053         }
10054         else if (rsurface.colormod[3] < 1)
10055         {
10056                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10057                 GL_DepthMask(false);
10058         }
10059         else
10060         {
10061                 GL_BlendFunc(GL_ONE, GL_ZERO);
10062                 GL_DepthMask(true);
10063         }
10064         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10065         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10066         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10067         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10068         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10069         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10070         for (i = 0, c = color4f;i < 6;i++, c += 4)
10071         {
10072                 c[0] *= rsurface.colormod[0];
10073                 c[1] *= rsurface.colormod[1];
10074                 c[2] *= rsurface.colormod[2];
10075                 c[3] *= rsurface.colormod[3];
10076         }
10077         if (r_refdef.fogenabled)
10078         {
10079                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10080                 {
10081                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10082                         f2 = 1 - f1;
10083                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10084                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10085                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10086                 }
10087         }
10088         R_Mesh_ResetTextureState();
10089         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10090         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10091 }
10092
10093 void R_DrawNoModel(entity_render_t *ent)
10094 {
10095         vec3_t org;
10096         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10097         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10098                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10099         else
10100                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10101 }
10102
10103 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10104 {
10105         vec3_t right1, right2, diff, normal;
10106
10107         VectorSubtract (org2, org1, normal);
10108
10109         // calculate 'right' vector for start
10110         VectorSubtract (r_refdef.view.origin, org1, diff);
10111         CrossProduct (normal, diff, right1);
10112         VectorNormalize (right1);
10113
10114         // calculate 'right' vector for end
10115         VectorSubtract (r_refdef.view.origin, org2, diff);
10116         CrossProduct (normal, diff, right2);
10117         VectorNormalize (right2);
10118
10119         vert[ 0] = org1[0] + width * right1[0];
10120         vert[ 1] = org1[1] + width * right1[1];
10121         vert[ 2] = org1[2] + width * right1[2];
10122         vert[ 3] = org1[0] - width * right1[0];
10123         vert[ 4] = org1[1] - width * right1[1];
10124         vert[ 5] = org1[2] - width * right1[2];
10125         vert[ 6] = org2[0] - width * right2[0];
10126         vert[ 7] = org2[1] - width * right2[1];
10127         vert[ 8] = org2[2] - width * right2[2];
10128         vert[ 9] = org2[0] + width * right2[0];
10129         vert[10] = org2[1] + width * right2[1];
10130         vert[11] = org2[2] + width * right2[2];
10131 }
10132
10133 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)
10134 {
10135         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10136         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10137         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10138         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10139         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10140         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10141         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10142         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10143         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10144         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10145         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10146         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10147 }
10148
10149 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10150 {
10151         int i;
10152         float *vertex3f;
10153         float v[3];
10154         VectorSet(v, x, y, z);
10155         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10156                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10157                         break;
10158         if (i == mesh->numvertices)
10159         {
10160                 if (mesh->numvertices < mesh->maxvertices)
10161                 {
10162                         VectorCopy(v, vertex3f);
10163                         mesh->numvertices++;
10164                 }
10165                 return mesh->numvertices;
10166         }
10167         else
10168                 return i;
10169 }
10170
10171 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10172 {
10173         int i;
10174         int *e, element[3];
10175         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10176         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10177         e = mesh->element3i + mesh->numtriangles * 3;
10178         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10179         {
10180                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10181                 if (mesh->numtriangles < mesh->maxtriangles)
10182                 {
10183                         *e++ = element[0];
10184                         *e++ = element[1];
10185                         *e++ = element[2];
10186                         mesh->numtriangles++;
10187                 }
10188                 element[1] = element[2];
10189         }
10190 }
10191
10192 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10193 {
10194         int i;
10195         int *e, element[3];
10196         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10197         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10198         e = mesh->element3i + mesh->numtriangles * 3;
10199         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10200         {
10201                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10202                 if (mesh->numtriangles < mesh->maxtriangles)
10203                 {
10204                         *e++ = element[0];
10205                         *e++ = element[1];
10206                         *e++ = element[2];
10207                         mesh->numtriangles++;
10208                 }
10209                 element[1] = element[2];
10210         }
10211 }
10212
10213 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10214 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10215 {
10216         int planenum, planenum2;
10217         int w;
10218         int tempnumpoints;
10219         mplane_t *plane, *plane2;
10220         double maxdist;
10221         double temppoints[2][256*3];
10222         // figure out how large a bounding box we need to properly compute this brush
10223         maxdist = 0;
10224         for (w = 0;w < numplanes;w++)
10225                 maxdist = max(maxdist, fabs(planes[w].dist));
10226         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10227         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10228         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10229         {
10230                 w = 0;
10231                 tempnumpoints = 4;
10232                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10233                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10234                 {
10235                         if (planenum2 == planenum)
10236                                 continue;
10237                         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);
10238                         w = !w;
10239                 }
10240                 if (tempnumpoints < 3)
10241                         continue;
10242                 // generate elements forming a triangle fan for this polygon
10243                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10244         }
10245 }
10246
10247 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)
10248 {
10249         texturelayer_t *layer;
10250         layer = t->currentlayers + t->currentnumlayers++;
10251         layer->type = type;
10252         layer->depthmask = depthmask;
10253         layer->blendfunc1 = blendfunc1;
10254         layer->blendfunc2 = blendfunc2;
10255         layer->texture = texture;
10256         layer->texmatrix = *matrix;
10257         layer->color[0] = r;
10258         layer->color[1] = g;
10259         layer->color[2] = b;
10260         layer->color[3] = a;
10261 }
10262
10263 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10264 {
10265         if(parms[0] == 0 && parms[1] == 0)
10266                 return false;
10267         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10268                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10269                         return false;
10270         return true;
10271 }
10272
10273 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10274 {
10275         double index, f;
10276         index = parms[2] + r_refdef.scene.time * parms[3];
10277         index -= floor(index);
10278         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10279         {
10280         default:
10281         case Q3WAVEFUNC_NONE:
10282         case Q3WAVEFUNC_NOISE:
10283         case Q3WAVEFUNC_COUNT:
10284                 f = 0;
10285                 break;
10286         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10287         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10288         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10289         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10290         case Q3WAVEFUNC_TRIANGLE:
10291                 index *= 4;
10292                 f = index - floor(index);
10293                 if (index < 1)
10294                         f = f;
10295                 else if (index < 2)
10296                         f = 1 - f;
10297                 else if (index < 3)
10298                         f = -f;
10299                 else
10300                         f = -(1 - f);
10301                 break;
10302         }
10303         f = parms[0] + parms[1] * f;
10304         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10305                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10306         return (float) f;
10307 }
10308
10309 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10310 {
10311         int w, h, idx;
10312         float f;
10313         float tcmat[12];
10314         matrix4x4_t matrix, temp;
10315         switch(tcmod->tcmod)
10316         {
10317                 case Q3TCMOD_COUNT:
10318                 case Q3TCMOD_NONE:
10319                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10320                                 matrix = r_waterscrollmatrix;
10321                         else
10322                                 matrix = identitymatrix;
10323                         break;
10324                 case Q3TCMOD_ENTITYTRANSLATE:
10325                         // this is used in Q3 to allow the gamecode to control texcoord
10326                         // scrolling on the entity, which is not supported in darkplaces yet.
10327                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10328                         break;
10329                 case Q3TCMOD_ROTATE:
10330                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10331                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10332                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10333                         break;
10334                 case Q3TCMOD_SCALE:
10335                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10336                         break;
10337                 case Q3TCMOD_SCROLL:
10338                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10339                         break;
10340                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10341                         w = (int) tcmod->parms[0];
10342                         h = (int) tcmod->parms[1];
10343                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10344                         f = f - floor(f);
10345                         idx = (int) floor(f * w * h);
10346                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10347                         break;
10348                 case Q3TCMOD_STRETCH:
10349                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10350                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10351                         break;
10352                 case Q3TCMOD_TRANSFORM:
10353                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10354                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10355                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10356                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10357                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10358                         break;
10359                 case Q3TCMOD_TURBULENT:
10360                         // this is handled in the RSurf_PrepareVertices function
10361                         matrix = identitymatrix;
10362                         break;
10363         }
10364         temp = *texmatrix;
10365         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10366 }
10367
10368 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10369 {
10370         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10371         char name[MAX_QPATH];
10372         skinframe_t *skinframe;
10373         unsigned char pixels[296*194];
10374         strlcpy(cache->name, skinname, sizeof(cache->name));
10375         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10376         if (developer_loading.integer)
10377                 Con_Printf("loading %s\n", name);
10378         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10379         if (!skinframe || !skinframe->base)
10380         {
10381                 unsigned char *f;
10382                 fs_offset_t filesize;
10383                 skinframe = NULL;
10384                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10385                 if (f)
10386                 {
10387                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10388                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10389                         Mem_Free(f);
10390                 }
10391         }
10392         cache->skinframe = skinframe;
10393 }
10394
10395 texture_t *R_GetCurrentTexture(texture_t *t)
10396 {
10397         int i;
10398         const entity_render_t *ent = rsurface.entity;
10399         dp_model_t *model = ent->model;
10400         q3shaderinfo_layer_tcmod_t *tcmod;
10401
10402         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10403                 return t->currentframe;
10404         t->update_lastrenderframe = r_textureframe;
10405         t->update_lastrenderentity = (void *)ent;
10406
10407         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10408                 t->camera_entity = ent->entitynumber;
10409         else
10410                 t->camera_entity = 0;
10411
10412         // switch to an alternate material if this is a q1bsp animated material
10413         {
10414                 texture_t *texture = t;
10415                 int s = rsurface.ent_skinnum;
10416                 if ((unsigned int)s >= (unsigned int)model->numskins)
10417                         s = 0;
10418                 if (model->skinscenes)
10419                 {
10420                         if (model->skinscenes[s].framecount > 1)
10421                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10422                         else
10423                                 s = model->skinscenes[s].firstframe;
10424                 }
10425                 if (s > 0)
10426                         t = t + s * model->num_surfaces;
10427                 if (t->animated)
10428                 {
10429                         // use an alternate animation if the entity's frame is not 0,
10430                         // and only if the texture has an alternate animation
10431                         if (rsurface.ent_alttextures && t->anim_total[1])
10432                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10433                         else
10434                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10435                 }
10436                 texture->currentframe = t;
10437         }
10438
10439         // update currentskinframe to be a qw skin or animation frame
10440         if (rsurface.ent_qwskin >= 0)
10441         {
10442                 i = rsurface.ent_qwskin;
10443                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10444                 {
10445                         r_qwskincache_size = cl.maxclients;
10446                         if (r_qwskincache)
10447                                 Mem_Free(r_qwskincache);
10448                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10449                 }
10450                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10451                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10452                 t->currentskinframe = r_qwskincache[i].skinframe;
10453                 if (t->currentskinframe == NULL)
10454                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10455         }
10456         else if (t->numskinframes >= 2)
10457                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10458         if (t->backgroundnumskinframes >= 2)
10459                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10460
10461         t->currentmaterialflags = t->basematerialflags;
10462         t->currentalpha = rsurface.colormod[3];
10463         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10464                 t->currentalpha *= r_wateralpha.value;
10465         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10466                 t->currentalpha *= t->r_water_wateralpha;
10467         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10468                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10469         if (!(rsurface.ent_flags & RENDER_LIGHT))
10470                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10471         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10472         {
10473                 // pick a model lighting mode
10474                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10475                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10476                 else
10477                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10478         }
10479         if (rsurface.ent_flags & RENDER_ADDITIVE)
10480                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10481         else if (t->currentalpha < 1)
10482                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10483         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10484                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10485         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10486                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10487         if (t->backgroundnumskinframes)
10488                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10489         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10490         {
10491                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10492                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10493         }
10494         else
10495                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10496         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10497                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10498
10499         // there is no tcmod
10500         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10501         {
10502                 t->currenttexmatrix = r_waterscrollmatrix;
10503                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10504         }
10505         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10506         {
10507                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10508                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10509         }
10510
10511         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10512                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10513         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10514                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10515
10516         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10517         if (t->currentskinframe->qpixels)
10518                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10519         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10520         if (!t->basetexture)
10521                 t->basetexture = r_texture_notexture;
10522         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10523         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10524         t->nmaptexture = t->currentskinframe->nmap;
10525         if (!t->nmaptexture)
10526                 t->nmaptexture = r_texture_blanknormalmap;
10527         t->glosstexture = r_texture_black;
10528         t->glowtexture = t->currentskinframe->glow;
10529         t->fogtexture = t->currentskinframe->fog;
10530         t->reflectmasktexture = t->currentskinframe->reflect;
10531         if (t->backgroundnumskinframes)
10532         {
10533                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10534                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10535                 t->backgroundglosstexture = r_texture_black;
10536                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10537                 if (!t->backgroundnmaptexture)
10538                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10539         }
10540         else
10541         {
10542                 t->backgroundbasetexture = r_texture_white;
10543                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10544                 t->backgroundglosstexture = r_texture_black;
10545                 t->backgroundglowtexture = NULL;
10546         }
10547         t->specularpower = r_shadow_glossexponent.value;
10548         // TODO: store reference values for these in the texture?
10549         t->specularscale = 0;
10550         if (r_shadow_gloss.integer > 0)
10551         {
10552                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10553                 {
10554                         if (r_shadow_glossintensity.value > 0)
10555                         {
10556                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10557                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10558                                 t->specularscale = r_shadow_glossintensity.value;
10559                         }
10560                 }
10561                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10562                 {
10563                         t->glosstexture = r_texture_white;
10564                         t->backgroundglosstexture = r_texture_white;
10565                         t->specularscale = r_shadow_gloss2intensity.value;
10566                         t->specularpower = r_shadow_gloss2exponent.value;
10567                 }
10568         }
10569         t->specularscale *= t->specularscalemod;
10570         t->specularpower *= t->specularpowermod;
10571
10572         // lightmaps mode looks bad with dlights using actual texturing, so turn
10573         // off the colormap and glossmap, but leave the normalmap on as it still
10574         // accurately represents the shading involved
10575         if (gl_lightmaps.integer)
10576         {
10577                 t->basetexture = r_texture_grey128;
10578                 t->pantstexture = r_texture_black;
10579                 t->shirttexture = r_texture_black;
10580                 t->nmaptexture = r_texture_blanknormalmap;
10581                 t->glosstexture = r_texture_black;
10582                 t->glowtexture = NULL;
10583                 t->fogtexture = NULL;
10584                 t->reflectmasktexture = NULL;
10585                 t->backgroundbasetexture = NULL;
10586                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10587                 t->backgroundglosstexture = r_texture_black;
10588                 t->backgroundglowtexture = NULL;
10589                 t->specularscale = 0;
10590                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10591         }
10592
10593         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10594         VectorClear(t->dlightcolor);
10595         t->currentnumlayers = 0;
10596         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10597         {
10598                 int blendfunc1, blendfunc2;
10599                 qboolean depthmask;
10600                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10601                 {
10602                         blendfunc1 = GL_SRC_ALPHA;
10603                         blendfunc2 = GL_ONE;
10604                 }
10605                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10606                 {
10607                         blendfunc1 = GL_SRC_ALPHA;
10608                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10609                 }
10610                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10611                 {
10612                         blendfunc1 = t->customblendfunc[0];
10613                         blendfunc2 = t->customblendfunc[1];
10614                 }
10615                 else
10616                 {
10617                         blendfunc1 = GL_ONE;
10618                         blendfunc2 = GL_ZERO;
10619                 }
10620                 // don't colormod evilblend textures
10621                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10622                         VectorSet(t->lightmapcolor, 1, 1, 1);
10623                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10624                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10625                 {
10626                         // fullbright is not affected by r_refdef.lightmapintensity
10627                         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]);
10628                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10629                                 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]);
10630                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10631                                 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]);
10632                 }
10633                 else
10634                 {
10635                         vec3_t ambientcolor;
10636                         float colorscale;
10637                         // set the color tint used for lights affecting this surface
10638                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10639                         colorscale = 2;
10640                         // q3bsp has no lightmap updates, so the lightstylevalue that
10641                         // would normally be baked into the lightmap must be
10642                         // applied to the color
10643                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10644                         if (model->type == mod_brushq3)
10645                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10646                         colorscale *= r_refdef.lightmapintensity;
10647                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10648                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10649                         // basic lit geometry
10650                         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]);
10651                         // add pants/shirt if needed
10652                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10653                                 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]);
10654                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10655                                 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]);
10656                         // now add ambient passes if needed
10657                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10658                         {
10659                                 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]);
10660                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10661                                         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]);
10662                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10663                                         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]);
10664                         }
10665                 }
10666                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10667                         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]);
10668                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10669                 {
10670                         // if this is opaque use alpha blend which will darken the earlier
10671                         // passes cheaply.
10672                         //
10673                         // if this is an alpha blended material, all the earlier passes
10674                         // were darkened by fog already, so we only need to add the fog
10675                         // color ontop through the fog mask texture
10676                         //
10677                         // if this is an additive blended material, all the earlier passes
10678                         // were darkened by fog already, and we should not add fog color
10679                         // (because the background was not darkened, there is no fog color
10680                         // that was lost behind it).
10681                         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]);
10682                 }
10683         }
10684
10685         return t->currentframe;
10686 }
10687
10688 rsurfacestate_t rsurface;
10689
10690 void R_Mesh_ResizeArrays(int newvertices)
10691 {
10692         unsigned char *base;
10693         size_t size;
10694         if (rsurface.array_size >= newvertices)
10695                 return;
10696         if (rsurface.array_base)
10697                 Mem_Free(rsurface.array_base);
10698         rsurface.array_size = (newvertices + 1023) & ~1023;
10699         size = 0;
10700         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10701         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10702         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10703         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10704         size += rsurface.array_size * sizeof(float[3]);
10705         size += rsurface.array_size * sizeof(float[3]);
10706         size += rsurface.array_size * sizeof(float[3]);
10707         size += rsurface.array_size * sizeof(float[3]);
10708         size += rsurface.array_size * sizeof(float[3]);
10709         size += rsurface.array_size * sizeof(float[3]);
10710         size += rsurface.array_size * sizeof(float[3]);
10711         size += rsurface.array_size * sizeof(float[3]);
10712         size += rsurface.array_size * sizeof(float[4]);
10713         size += rsurface.array_size * sizeof(float[2]);
10714         size += rsurface.array_size * sizeof(float[2]);
10715         size += rsurface.array_size * sizeof(float[4]);
10716         size += rsurface.array_size * sizeof(int[3]);
10717         size += rsurface.array_size * sizeof(unsigned short[3]);
10718         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10719         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10720         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10721         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10722         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10723         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10724         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10725         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10726         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10727         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10728         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10729         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10730         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10731         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10732         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10733         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10734         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10735         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10736         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10737 }
10738
10739 void RSurf_ActiveWorldEntity(void)
10740 {
10741         dp_model_t *model = r_refdef.scene.worldmodel;
10742         //if (rsurface.entity == r_refdef.scene.worldentity)
10743         //      return;
10744         rsurface.entity = r_refdef.scene.worldentity;
10745         rsurface.skeleton = NULL;
10746         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10747         rsurface.ent_skinnum = 0;
10748         rsurface.ent_qwskin = -1;
10749         rsurface.ent_shadertime = 0;
10750         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10751         if (rsurface.array_size < model->surfmesh.num_vertices)
10752                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10753         rsurface.matrix = identitymatrix;
10754         rsurface.inversematrix = identitymatrix;
10755         rsurface.matrixscale = 1;
10756         rsurface.inversematrixscale = 1;
10757         R_EntityMatrix(&identitymatrix);
10758         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10759         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10760         rsurface.fograngerecip = r_refdef.fograngerecip;
10761         rsurface.fogheightfade = r_refdef.fogheightfade;
10762         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10763         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10764         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10765         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10766         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10767         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10768         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10769         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10770         rsurface.colormod[3] = 1;
10771         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);
10772         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10773         rsurface.frameblend[0].lerp = 1;
10774         rsurface.ent_alttextures = false;
10775         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10776         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10777         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10778         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10779         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10780         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10781         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10782         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10783         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10784         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10785         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10786         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10787         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10788         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10789         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10790         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10791         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10792         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10793         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10794         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10795         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10796         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10797         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10798         rsurface.modelelement3i = model->surfmesh.data_element3i;
10799         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10800         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10801         rsurface.modelelement3s = model->surfmesh.data_element3s;
10802         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10803         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10804         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10805         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10806         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10807         rsurface.modelsurfaces = model->data_surfaces;
10808         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10809         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10810         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10811         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10812         rsurface.modelgeneratedvertex = false;
10813         rsurface.batchgeneratedvertex = false;
10814         rsurface.batchfirstvertex = 0;
10815         rsurface.batchnumvertices = 0;
10816         rsurface.batchfirsttriangle = 0;
10817         rsurface.batchnumtriangles = 0;
10818         rsurface.batchvertex3f  = NULL;
10819         rsurface.batchvertex3f_vertexbuffer = NULL;
10820         rsurface.batchvertex3f_bufferoffset = 0;
10821         rsurface.batchsvector3f = NULL;
10822         rsurface.batchsvector3f_vertexbuffer = NULL;
10823         rsurface.batchsvector3f_bufferoffset = 0;
10824         rsurface.batchtvector3f = NULL;
10825         rsurface.batchtvector3f_vertexbuffer = NULL;
10826         rsurface.batchtvector3f_bufferoffset = 0;
10827         rsurface.batchnormal3f  = NULL;
10828         rsurface.batchnormal3f_vertexbuffer = NULL;
10829         rsurface.batchnormal3f_bufferoffset = 0;
10830         rsurface.batchlightmapcolor4f = NULL;
10831         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10832         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10833         rsurface.batchtexcoordtexture2f = NULL;
10834         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10835         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10836         rsurface.batchtexcoordlightmap2f = NULL;
10837         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10838         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10839         rsurface.batchvertexmesh = NULL;
10840         rsurface.batchvertexmeshbuffer = NULL;
10841         rsurface.batchvertexposition = NULL;
10842         rsurface.batchvertexpositionbuffer = NULL;
10843         rsurface.batchelement3i = NULL;
10844         rsurface.batchelement3i_indexbuffer = NULL;
10845         rsurface.batchelement3i_bufferoffset = 0;
10846         rsurface.batchelement3s = NULL;
10847         rsurface.batchelement3s_indexbuffer = NULL;
10848         rsurface.batchelement3s_bufferoffset = 0;
10849         rsurface.passcolor4f = NULL;
10850         rsurface.passcolor4f_vertexbuffer = NULL;
10851         rsurface.passcolor4f_bufferoffset = 0;
10852 }
10853
10854 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10855 {
10856         dp_model_t *model = ent->model;
10857         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10858         //      return;
10859         rsurface.entity = (entity_render_t *)ent;
10860         rsurface.skeleton = ent->skeleton;
10861         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10862         rsurface.ent_skinnum = ent->skinnum;
10863         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;
10864         rsurface.ent_shadertime = ent->shadertime;
10865         rsurface.ent_flags = ent->flags;
10866         if (rsurface.array_size < model->surfmesh.num_vertices)
10867                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10868         rsurface.matrix = ent->matrix;
10869         rsurface.inversematrix = ent->inversematrix;
10870         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10871         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10872         R_EntityMatrix(&rsurface.matrix);
10873         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10874         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10875         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10876         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10877         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10878         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10879         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10880         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10881         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10882         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10883         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10884         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10885         rsurface.colormod[3] = ent->alpha;
10886         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10887         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10888         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10889         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10890         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10891         if (ent->model->brush.submodel && !prepass)
10892         {
10893                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10894                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10895         }
10896         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10897         {
10898                 if (ent->animcache_vertex3f && !r_framedata_failed)
10899                 {
10900                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10901                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10902                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10903                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10904                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10905                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10906                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10907                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10908                 }
10909                 else if (wanttangents)
10910                 {
10911                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10912                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10913                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10914                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10915                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10916                         rsurface.modelvertexmesh = NULL;
10917                         rsurface.modelvertexmeshbuffer = NULL;
10918                         rsurface.modelvertexposition = NULL;
10919                         rsurface.modelvertexpositionbuffer = NULL;
10920                 }
10921                 else if (wantnormals)
10922                 {
10923                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10924                         rsurface.modelsvector3f = NULL;
10925                         rsurface.modeltvector3f = NULL;
10926                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10927                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10928                         rsurface.modelvertexmesh = NULL;
10929                         rsurface.modelvertexmeshbuffer = NULL;
10930                         rsurface.modelvertexposition = NULL;
10931                         rsurface.modelvertexpositionbuffer = NULL;
10932                 }
10933                 else
10934                 {
10935                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10936                         rsurface.modelsvector3f = NULL;
10937                         rsurface.modeltvector3f = NULL;
10938                         rsurface.modelnormal3f = NULL;
10939                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10940                         rsurface.modelvertexmesh = NULL;
10941                         rsurface.modelvertexmeshbuffer = NULL;
10942                         rsurface.modelvertexposition = NULL;
10943                         rsurface.modelvertexpositionbuffer = NULL;
10944                 }
10945                 rsurface.modelvertex3f_vertexbuffer = 0;
10946                 rsurface.modelvertex3f_bufferoffset = 0;
10947                 rsurface.modelsvector3f_vertexbuffer = 0;
10948                 rsurface.modelsvector3f_bufferoffset = 0;
10949                 rsurface.modeltvector3f_vertexbuffer = 0;
10950                 rsurface.modeltvector3f_bufferoffset = 0;
10951                 rsurface.modelnormal3f_vertexbuffer = 0;
10952                 rsurface.modelnormal3f_bufferoffset = 0;
10953                 rsurface.modelgeneratedvertex = true;
10954         }
10955         else
10956         {
10957                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10958                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10959                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10960                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10961                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10962                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10963                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10964                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10965                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10966                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10967                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10968                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10969                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10970                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10971                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10972                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10973                 rsurface.modelgeneratedvertex = false;
10974         }
10975         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10976         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10977         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10978         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10979         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10980         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10981         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10982         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10983         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10984         rsurface.modelelement3i = model->surfmesh.data_element3i;
10985         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10986         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10987         rsurface.modelelement3s = model->surfmesh.data_element3s;
10988         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10989         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10990         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10991         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10992         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10993         rsurface.modelsurfaces = model->data_surfaces;
10994         rsurface.batchgeneratedvertex = false;
10995         rsurface.batchfirstvertex = 0;
10996         rsurface.batchnumvertices = 0;
10997         rsurface.batchfirsttriangle = 0;
10998         rsurface.batchnumtriangles = 0;
10999         rsurface.batchvertex3f  = NULL;
11000         rsurface.batchvertex3f_vertexbuffer = NULL;
11001         rsurface.batchvertex3f_bufferoffset = 0;
11002         rsurface.batchsvector3f = NULL;
11003         rsurface.batchsvector3f_vertexbuffer = NULL;
11004         rsurface.batchsvector3f_bufferoffset = 0;
11005         rsurface.batchtvector3f = NULL;
11006         rsurface.batchtvector3f_vertexbuffer = NULL;
11007         rsurface.batchtvector3f_bufferoffset = 0;
11008         rsurface.batchnormal3f  = NULL;
11009         rsurface.batchnormal3f_vertexbuffer = NULL;
11010         rsurface.batchnormal3f_bufferoffset = 0;
11011         rsurface.batchlightmapcolor4f = NULL;
11012         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11013         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11014         rsurface.batchtexcoordtexture2f = NULL;
11015         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11016         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11017         rsurface.batchtexcoordlightmap2f = NULL;
11018         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11019         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11020         rsurface.batchvertexmesh = NULL;
11021         rsurface.batchvertexmeshbuffer = NULL;
11022         rsurface.batchvertexposition = NULL;
11023         rsurface.batchvertexpositionbuffer = NULL;
11024         rsurface.batchelement3i = NULL;
11025         rsurface.batchelement3i_indexbuffer = NULL;
11026         rsurface.batchelement3i_bufferoffset = 0;
11027         rsurface.batchelement3s = NULL;
11028         rsurface.batchelement3s_indexbuffer = NULL;
11029         rsurface.batchelement3s_bufferoffset = 0;
11030         rsurface.passcolor4f = NULL;
11031         rsurface.passcolor4f_vertexbuffer = NULL;
11032         rsurface.passcolor4f_bufferoffset = 0;
11033 }
11034
11035 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)
11036 {
11037         int i;
11038
11039         rsurface.entity = r_refdef.scene.worldentity;
11040         rsurface.skeleton = NULL;
11041         rsurface.ent_skinnum = 0;
11042         rsurface.ent_qwskin = -1;
11043         rsurface.ent_shadertime = shadertime;
11044         rsurface.ent_flags = entflags;
11045         rsurface.modelnumvertices = numvertices;
11046         rsurface.modelnumtriangles = numtriangles;
11047         if (rsurface.array_size < rsurface.modelnumvertices)
11048                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11049         rsurface.matrix = *matrix;
11050         rsurface.inversematrix = *inversematrix;
11051         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11052         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11053         R_EntityMatrix(&rsurface.matrix);
11054         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11055         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11056         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11057         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11058         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11059         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11060         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11061         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11062         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11063         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11064         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11065         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11066         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);
11067         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11068         rsurface.frameblend[0].lerp = 1;
11069         rsurface.ent_alttextures = false;
11070         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11071         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11072         if (wanttangents)
11073         {
11074                 rsurface.modelvertex3f = vertex3f;
11075                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11076                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11077                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11078         }
11079         else if (wantnormals)
11080         {
11081                 rsurface.modelvertex3f = vertex3f;
11082                 rsurface.modelsvector3f = NULL;
11083                 rsurface.modeltvector3f = NULL;
11084                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11085         }
11086         else
11087         {
11088                 rsurface.modelvertex3f = vertex3f;
11089                 rsurface.modelsvector3f = NULL;
11090                 rsurface.modeltvector3f = NULL;
11091                 rsurface.modelnormal3f = NULL;
11092         }
11093         rsurface.modelvertexmesh = NULL;
11094         rsurface.modelvertexmeshbuffer = NULL;
11095         rsurface.modelvertexposition = NULL;
11096         rsurface.modelvertexpositionbuffer = NULL;
11097         rsurface.modelvertex3f_vertexbuffer = 0;
11098         rsurface.modelvertex3f_bufferoffset = 0;
11099         rsurface.modelsvector3f_vertexbuffer = 0;
11100         rsurface.modelsvector3f_bufferoffset = 0;
11101         rsurface.modeltvector3f_vertexbuffer = 0;
11102         rsurface.modeltvector3f_bufferoffset = 0;
11103         rsurface.modelnormal3f_vertexbuffer = 0;
11104         rsurface.modelnormal3f_bufferoffset = 0;
11105         rsurface.modelgeneratedvertex = true;
11106         rsurface.modellightmapcolor4f  = color4f;
11107         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11108         rsurface.modellightmapcolor4f_bufferoffset = 0;
11109         rsurface.modeltexcoordtexture2f  = texcoord2f;
11110         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11111         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11112         rsurface.modeltexcoordlightmap2f  = NULL;
11113         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11114         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11115         rsurface.modelelement3i = element3i;
11116         rsurface.modelelement3i_indexbuffer = NULL;
11117         rsurface.modelelement3i_bufferoffset = 0;
11118         rsurface.modelelement3s = element3s;
11119         rsurface.modelelement3s_indexbuffer = NULL;
11120         rsurface.modelelement3s_bufferoffset = 0;
11121         rsurface.modellightmapoffsets = NULL;
11122         rsurface.modelsurfaces = NULL;
11123         rsurface.batchgeneratedvertex = false;
11124         rsurface.batchfirstvertex = 0;
11125         rsurface.batchnumvertices = 0;
11126         rsurface.batchfirsttriangle = 0;
11127         rsurface.batchnumtriangles = 0;
11128         rsurface.batchvertex3f  = NULL;
11129         rsurface.batchvertex3f_vertexbuffer = NULL;
11130         rsurface.batchvertex3f_bufferoffset = 0;
11131         rsurface.batchsvector3f = NULL;
11132         rsurface.batchsvector3f_vertexbuffer = NULL;
11133         rsurface.batchsvector3f_bufferoffset = 0;
11134         rsurface.batchtvector3f = NULL;
11135         rsurface.batchtvector3f_vertexbuffer = NULL;
11136         rsurface.batchtvector3f_bufferoffset = 0;
11137         rsurface.batchnormal3f  = NULL;
11138         rsurface.batchnormal3f_vertexbuffer = NULL;
11139         rsurface.batchnormal3f_bufferoffset = 0;
11140         rsurface.batchlightmapcolor4f = NULL;
11141         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11142         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11143         rsurface.batchtexcoordtexture2f = NULL;
11144         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11145         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11146         rsurface.batchtexcoordlightmap2f = NULL;
11147         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11148         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11149         rsurface.batchvertexmesh = NULL;
11150         rsurface.batchvertexmeshbuffer = NULL;
11151         rsurface.batchvertexposition = NULL;
11152         rsurface.batchvertexpositionbuffer = NULL;
11153         rsurface.batchelement3i = NULL;
11154         rsurface.batchelement3i_indexbuffer = NULL;
11155         rsurface.batchelement3i_bufferoffset = 0;
11156         rsurface.batchelement3s = NULL;
11157         rsurface.batchelement3s_indexbuffer = NULL;
11158         rsurface.batchelement3s_bufferoffset = 0;
11159         rsurface.passcolor4f = NULL;
11160         rsurface.passcolor4f_vertexbuffer = NULL;
11161         rsurface.passcolor4f_bufferoffset = 0;
11162
11163         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11164         {
11165                 if ((wantnormals || wanttangents) && !normal3f)
11166                 {
11167                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11168                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11169                 }
11170                 if (wanttangents && !svector3f)
11171                 {
11172                         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);
11173                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11174                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11175                 }
11176         }
11177
11178         // now convert arrays into vertexmesh structs
11179         for (i = 0;i < numvertices;i++)
11180         {
11181                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11182                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11183                 if (rsurface.modelsvector3f)
11184                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11185                 if (rsurface.modeltvector3f)
11186                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11187                 if (rsurface.modelnormal3f)
11188                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11189                 if (rsurface.modellightmapcolor4f)
11190                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11191                 if (rsurface.modeltexcoordtexture2f)
11192                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11193                 if (rsurface.modeltexcoordlightmap2f)
11194                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11195         }
11196 }
11197
11198 float RSurf_FogPoint(const float *v)
11199 {
11200         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11201         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11202         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11203         float FogHeightFade = r_refdef.fogheightfade;
11204         float fogfrac;
11205         unsigned int fogmasktableindex;
11206         if (r_refdef.fogplaneviewabove)
11207                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11208         else
11209                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11210         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11211         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11212 }
11213
11214 float RSurf_FogVertex(const float *v)
11215 {
11216         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11217         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11218         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11219         float FogHeightFade = rsurface.fogheightfade;
11220         float fogfrac;
11221         unsigned int fogmasktableindex;
11222         if (r_refdef.fogplaneviewabove)
11223                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11224         else
11225                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11226         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11227         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11228 }
11229
11230 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11231 {
11232         int i;
11233         for (i = 0;i < numelements;i++)
11234                 outelement3i[i] = inelement3i[i] + adjust;
11235 }
11236
11237 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11238 extern cvar_t gl_vbo;
11239 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11240 {
11241         int deformindex;
11242         int firsttriangle;
11243         int numtriangles;
11244         int firstvertex;
11245         int endvertex;
11246         int numvertices;
11247         int surfacefirsttriangle;
11248         int surfacenumtriangles;
11249         int surfacefirstvertex;
11250         int surfaceendvertex;
11251         int surfacenumvertices;
11252         int surfaceadjustvertex;
11253         int needsupdate;
11254         int i, j;
11255         qboolean gaps;
11256         qboolean dynamicvertex;
11257         float amplitude;
11258         float animpos;
11259         float scale;
11260         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11261         float waveparms[4];
11262         q3shaderinfo_deform_t *deform;
11263         const msurface_t *surface, *firstsurface;
11264         r_vertexposition_t *vertexposition;
11265         r_vertexmesh_t *vertexmesh;
11266         if (!texturenumsurfaces)
11267                 return;
11268         // find vertex range of this surface batch
11269         gaps = false;
11270         firstsurface = texturesurfacelist[0];
11271         firsttriangle = firstsurface->num_firsttriangle;
11272         numtriangles = 0;
11273         firstvertex = endvertex = firstsurface->num_firstvertex;
11274         for (i = 0;i < texturenumsurfaces;i++)
11275         {
11276                 surface = texturesurfacelist[i];
11277                 if (surface != firstsurface + i)
11278                         gaps = true;
11279                 surfacefirstvertex = surface->num_firstvertex;
11280                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11281                 surfacenumtriangles = surface->num_triangles;
11282                 if (firstvertex > surfacefirstvertex)
11283                         firstvertex = surfacefirstvertex;
11284                 if (endvertex < surfaceendvertex)
11285                         endvertex = surfaceendvertex;
11286                 numtriangles += surfacenumtriangles;
11287         }
11288         if (!numtriangles)
11289                 return;
11290
11291         // we now know the vertex range used, and if there are any gaps in it
11292         rsurface.batchfirstvertex = firstvertex;
11293         rsurface.batchnumvertices = endvertex - firstvertex;
11294         rsurface.batchfirsttriangle = firsttriangle;
11295         rsurface.batchnumtriangles = numtriangles;
11296
11297         // this variable holds flags for which properties have been updated that
11298         // may require regenerating vertexmesh or vertexposition arrays...
11299         needsupdate = 0;
11300
11301         // check if any dynamic vertex processing must occur
11302         dynamicvertex = false;
11303
11304         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11305                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11306         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11307         {
11308                 switch (deform->deform)
11309                 {
11310                 default:
11311                 case Q3DEFORM_PROJECTIONSHADOW:
11312                 case Q3DEFORM_TEXT0:
11313                 case Q3DEFORM_TEXT1:
11314                 case Q3DEFORM_TEXT2:
11315                 case Q3DEFORM_TEXT3:
11316                 case Q3DEFORM_TEXT4:
11317                 case Q3DEFORM_TEXT5:
11318                 case Q3DEFORM_TEXT6:
11319                 case Q3DEFORM_TEXT7:
11320                 case Q3DEFORM_NONE:
11321                         break;
11322                 case Q3DEFORM_AUTOSPRITE:
11323                         dynamicvertex = true;
11324                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11325                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11326                         break;
11327                 case Q3DEFORM_AUTOSPRITE2:
11328                         dynamicvertex = true;
11329                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11330                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11331                         break;
11332                 case Q3DEFORM_NORMAL:
11333                         dynamicvertex = true;
11334                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11335                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11336                         break;
11337                 case Q3DEFORM_WAVE:
11338                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11339                                 break; // if wavefunc is a nop, ignore this transform
11340                         dynamicvertex = true;
11341                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11342                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11343                         break;
11344                 case Q3DEFORM_BULGE:
11345                         dynamicvertex = true;
11346                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11347                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11348                         break;
11349                 case Q3DEFORM_MOVE:
11350                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11351                                 break; // if wavefunc is a nop, ignore this transform
11352                         dynamicvertex = true;
11353                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11354                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11355                         break;
11356                 }
11357         }
11358         switch(rsurface.texture->tcgen.tcgen)
11359         {
11360         default:
11361         case Q3TCGEN_TEXTURE:
11362                 break;
11363         case Q3TCGEN_LIGHTMAP:
11364                 dynamicvertex = true;
11365                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11366                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11367                 break;
11368         case Q3TCGEN_VECTOR:
11369                 dynamicvertex = true;
11370                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11371                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11372                 break;
11373         case Q3TCGEN_ENVIRONMENT:
11374                 dynamicvertex = true;
11375                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11376                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11377                 break;
11378         }
11379         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11380         {
11381                 dynamicvertex = true;
11382                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11383                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11384         }
11385
11386         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11387         {
11388                 dynamicvertex = true;
11389                 batchneed |= BATCHNEED_NOGAPS;
11390                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11391         }
11392
11393         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11394         {
11395                 dynamicvertex = true;
11396                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11397                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11398         }
11399
11400         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11401         {
11402                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11403                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11404                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11405                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11406                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11407                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11408                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11409         }
11410
11411         // when the model data has no vertex buffer (dynamic mesh), we need to
11412         // eliminate gaps
11413         if (!rsurface.modelvertexmeshbuffer)
11414                 batchneed |= BATCHNEED_NOGAPS;
11415
11416         // if needsupdate, we have to do a dynamic vertex batch for sure
11417         if (needsupdate & batchneed)
11418                 dynamicvertex = true;
11419
11420         // see if we need to build vertexmesh from arrays
11421         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11422                 dynamicvertex = true;
11423
11424         // see if we need to build vertexposition from arrays
11425         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11426                 dynamicvertex = true;
11427
11428         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11429         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11430                 dynamicvertex = true;
11431
11432         // if there is a chance of animated vertex colors, it's a dynamic batch
11433         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11434                 dynamicvertex = true;
11435
11436         rsurface.batchvertex3f = rsurface.modelvertex3f;
11437         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11438         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11439         rsurface.batchsvector3f = rsurface.modelsvector3f;
11440         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11441         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11442         rsurface.batchtvector3f = rsurface.modeltvector3f;
11443         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11444         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11445         rsurface.batchnormal3f = rsurface.modelnormal3f;
11446         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11447         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11448         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11449         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11450         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11451         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11452         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11453         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11454         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11455         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11456         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11457         rsurface.batchvertexposition = rsurface.modelvertexposition;
11458         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11459         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11460         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11461         rsurface.batchelement3i = rsurface.modelelement3i;
11462         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11463         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11464         rsurface.batchelement3s = rsurface.modelelement3s;
11465         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11466         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11467
11468         // if any dynamic vertex processing has to occur in software, we copy the
11469         // entire surface list together before processing to rebase the vertices
11470         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11471         //
11472         // if any gaps exist and we do not have a static vertex buffer, we have to
11473         // copy the surface list together to avoid wasting upload bandwidth on the
11474         // vertices in the gaps.
11475         //
11476         // if gaps exist and we have a static vertex buffer, we still have to
11477         // combine the index buffer ranges into one dynamic index buffer.
11478         //
11479         // in all cases we end up with data that can be drawn in one call.
11480
11481         if (!dynamicvertex)
11482         {
11483                 // static vertex data, just set pointers...
11484                 rsurface.batchgeneratedvertex = false;
11485                 // if there are gaps, we want to build a combined index buffer,
11486                 // otherwise use the original static buffer with an appropriate offset
11487                 if (gaps)
11488                 {
11489                         firsttriangle = 0;
11490                         numtriangles = 0;
11491                         for (i = 0;i < texturenumsurfaces;i++)
11492                         {
11493                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11494                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11495                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11496                                 numtriangles += surfacenumtriangles;
11497                         }
11498                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11499                         rsurface.batchelement3i_indexbuffer = NULL;
11500                         rsurface.batchelement3i_bufferoffset = 0;
11501                         rsurface.batchelement3s = NULL;
11502                         rsurface.batchelement3s_indexbuffer = NULL;
11503                         rsurface.batchelement3s_bufferoffset = 0;
11504                         if (endvertex <= 65536)
11505                         {
11506                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11507                                 for (i = 0;i < numtriangles*3;i++)
11508                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11509                         }
11510                         rsurface.batchfirsttriangle = firsttriangle;
11511                         rsurface.batchnumtriangles = numtriangles;
11512                 }
11513                 return;
11514         }
11515
11516         // something needs software processing, do it for real...
11517         // we only directly handle interleaved array data in this case...
11518         rsurface.batchgeneratedvertex = true;
11519
11520         // now copy the vertex data into a combined array and make an index array
11521         // (this is what Quake3 does all the time)
11522         //if (gaps || rsurface.batchfirstvertex)
11523         {
11524                 rsurface.batchvertexposition = NULL;
11525                 rsurface.batchvertexpositionbuffer = NULL;
11526                 rsurface.batchvertexmesh = NULL;
11527                 rsurface.batchvertexmeshbuffer = NULL;
11528                 rsurface.batchvertex3f = NULL;
11529                 rsurface.batchvertex3f_vertexbuffer = NULL;
11530                 rsurface.batchvertex3f_bufferoffset = 0;
11531                 rsurface.batchsvector3f = NULL;
11532                 rsurface.batchsvector3f_vertexbuffer = NULL;
11533                 rsurface.batchsvector3f_bufferoffset = 0;
11534                 rsurface.batchtvector3f = NULL;
11535                 rsurface.batchtvector3f_vertexbuffer = NULL;
11536                 rsurface.batchtvector3f_bufferoffset = 0;
11537                 rsurface.batchnormal3f = NULL;
11538                 rsurface.batchnormal3f_vertexbuffer = NULL;
11539                 rsurface.batchnormal3f_bufferoffset = 0;
11540                 rsurface.batchlightmapcolor4f = NULL;
11541                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11542                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11543                 rsurface.batchtexcoordtexture2f = NULL;
11544                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11545                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11546                 rsurface.batchtexcoordlightmap2f = NULL;
11547                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11548                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11549                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11550                 rsurface.batchelement3i_indexbuffer = NULL;
11551                 rsurface.batchelement3i_bufferoffset = 0;
11552                 rsurface.batchelement3s = NULL;
11553                 rsurface.batchelement3s_indexbuffer = NULL;
11554                 rsurface.batchelement3s_bufferoffset = 0;
11555                 // we'll only be setting up certain arrays as needed
11556                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11557                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11558                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11559                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11560                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11561                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11562                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11563                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11564                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11565                 {
11566                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11567                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11568                 }
11569                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11570                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11571                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11572                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11573                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11574                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11575                 numvertices = 0;
11576                 numtriangles = 0;
11577                 for (i = 0;i < texturenumsurfaces;i++)
11578                 {
11579                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11580                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11581                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11582                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11583                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11584                         // copy only the data requested
11585                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11586                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11587                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11588                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11589                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11590                         {
11591                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11592                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11593                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11594                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11595                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11596                                 {
11597                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11598                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11599                                 }
11600                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11601                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11602                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11603                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11604                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11605                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11606                         }
11607                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11608                         numvertices += surfacenumvertices;
11609                         numtriangles += surfacenumtriangles;
11610                 }
11611
11612                 // generate a 16bit index array as well if possible
11613                 // (in general, dynamic batches fit)
11614                 if (numvertices <= 65536)
11615                 {
11616                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11617                         for (i = 0;i < numtriangles*3;i++)
11618                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11619                 }
11620
11621                 // since we've copied everything, the batch now starts at 0
11622                 rsurface.batchfirstvertex = 0;
11623                 rsurface.batchnumvertices = numvertices;
11624                 rsurface.batchfirsttriangle = 0;
11625                 rsurface.batchnumtriangles = numtriangles;
11626         }
11627
11628         // q1bsp surfaces rendered in vertex color mode have to have colors
11629         // calculated based on lightstyles
11630         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11631         {
11632                 // generate color arrays for the surfaces in this list
11633                 int c[4];
11634                 int scale;
11635                 int size3;
11636                 const int *offsets;
11637                 const unsigned char *lm;
11638                 numvertices = 0;
11639                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11640                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11641                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11642                 for (i = 0;i < texturenumsurfaces;i++)
11643                 {
11644                         surface = texturesurfacelist[i];
11645                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11646                         surfacenumvertices = surface->num_vertices;
11647                         if (surface->lightmapinfo->samples)
11648                         {
11649                                 for (j = 0;j < surfacenumvertices;j++)
11650                                 {
11651                                         lm = surface->lightmapinfo->samples + offsets[j];
11652                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11653                                         VectorScale(lm, scale, c);
11654                                         if (surface->lightmapinfo->styles[1] != 255)
11655                                         {
11656                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11657                                                 lm += size3;
11658                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11659                                                 VectorMA(c, scale, lm, c);
11660                                                 if (surface->lightmapinfo->styles[2] != 255)
11661                                                 {
11662                                                         lm += size3;
11663                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11664                                                         VectorMA(c, scale, lm, c);
11665                                                         if (surface->lightmapinfo->styles[3] != 255)
11666                                                         {
11667                                                                 lm += size3;
11668                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11669                                                                 VectorMA(c, scale, lm, c);
11670                                                         }
11671                                                 }
11672                                         }
11673                                         c[0] >>= 15;
11674                                         c[1] >>= 15;
11675                                         c[2] >>= 15;
11676                                         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);
11677                                         numvertices++;
11678                                 }
11679                         }
11680                         else
11681                         {
11682                                 for (j = 0;j < surfacenumvertices;j++)
11683                                 {
11684                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11685                                         numvertices++;
11686                                 }
11687                         }
11688                 }
11689         }
11690
11691         // if vertices are deformed (sprite flares and things in maps, possibly
11692         // water waves, bulges and other deformations), modify the copied vertices
11693         // in place
11694         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11695         {
11696                 switch (deform->deform)
11697                 {
11698                 default:
11699                 case Q3DEFORM_PROJECTIONSHADOW:
11700                 case Q3DEFORM_TEXT0:
11701                 case Q3DEFORM_TEXT1:
11702                 case Q3DEFORM_TEXT2:
11703                 case Q3DEFORM_TEXT3:
11704                 case Q3DEFORM_TEXT4:
11705                 case Q3DEFORM_TEXT5:
11706                 case Q3DEFORM_TEXT6:
11707                 case Q3DEFORM_TEXT7:
11708                 case Q3DEFORM_NONE:
11709                         break;
11710                 case Q3DEFORM_AUTOSPRITE:
11711                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11712                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11713                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11714                         VectorNormalize(newforward);
11715                         VectorNormalize(newright);
11716                         VectorNormalize(newup);
11717                         // a single autosprite surface can contain multiple sprites...
11718                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11719                         {
11720                                 VectorClear(center);
11721                                 for (i = 0;i < 4;i++)
11722                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11723                                 VectorScale(center, 0.25f, center);
11724                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11725                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11726                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11727                                 for (i = 0;i < 4;i++)
11728                                 {
11729                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11730                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11731                                 }
11732                         }
11733                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11734                         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);
11735                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11736                         rsurface.batchvertex3f_vertexbuffer = NULL;
11737                         rsurface.batchvertex3f_bufferoffset = 0;
11738                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11739                         rsurface.batchsvector3f_vertexbuffer = NULL;
11740                         rsurface.batchsvector3f_bufferoffset = 0;
11741                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11742                         rsurface.batchtvector3f_vertexbuffer = NULL;
11743                         rsurface.batchtvector3f_bufferoffset = 0;
11744                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11745                         rsurface.batchnormal3f_vertexbuffer = NULL;
11746                         rsurface.batchnormal3f_bufferoffset = 0;
11747                         break;
11748                 case Q3DEFORM_AUTOSPRITE2:
11749                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11750                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11751                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11752                         VectorNormalize(newforward);
11753                         VectorNormalize(newright);
11754                         VectorNormalize(newup);
11755                         {
11756                                 const float *v1, *v2;
11757                                 vec3_t start, end;
11758                                 float f, l;
11759                                 struct
11760                                 {
11761                                         float length2;
11762                                         const float *v1;
11763                                         const float *v2;
11764                                 }
11765                                 shortest[2];
11766                                 memset(shortest, 0, sizeof(shortest));
11767                                 // a single autosprite surface can contain multiple sprites...
11768                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11769                                 {
11770                                         VectorClear(center);
11771                                         for (i = 0;i < 4;i++)
11772                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11773                                         VectorScale(center, 0.25f, center);
11774                                         // find the two shortest edges, then use them to define the
11775                                         // axis vectors for rotating around the central axis
11776                                         for (i = 0;i < 6;i++)
11777                                         {
11778                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11779                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11780                                                 l = VectorDistance2(v1, v2);
11781                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11782                                                 if (v1[2] != v2[2])
11783                                                         l += (1.0f / 1024.0f);
11784                                                 if (shortest[0].length2 > l || i == 0)
11785                                                 {
11786                                                         shortest[1] = shortest[0];
11787                                                         shortest[0].length2 = l;
11788                                                         shortest[0].v1 = v1;
11789                                                         shortest[0].v2 = v2;
11790                                                 }
11791                                                 else if (shortest[1].length2 > l || i == 1)
11792                                                 {
11793                                                         shortest[1].length2 = l;
11794                                                         shortest[1].v1 = v1;
11795                                                         shortest[1].v2 = v2;
11796                                                 }
11797                                         }
11798                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11799                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11800                                         // this calculates the right vector from the shortest edge
11801                                         // and the up vector from the edge midpoints
11802                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11803                                         VectorNormalize(right);
11804                                         VectorSubtract(end, start, up);
11805                                         VectorNormalize(up);
11806                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11807                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11808                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11809                                         VectorNegate(forward, forward);
11810                                         VectorReflect(forward, 0, up, forward);
11811                                         VectorNormalize(forward);
11812                                         CrossProduct(up, forward, newright);
11813                                         VectorNormalize(newright);
11814                                         // rotate the quad around the up axis vector, this is made
11815                                         // especially easy by the fact we know the quad is flat,
11816                                         // so we only have to subtract the center position and
11817                                         // measure distance along the right vector, and then
11818                                         // multiply that by the newright vector and add back the
11819                                         // center position
11820                                         // we also need to subtract the old position to undo the
11821                                         // displacement from the center, which we do with a
11822                                         // DotProduct, the subtraction/addition of center is also
11823                                         // optimized into DotProducts here
11824                                         l = DotProduct(right, center);
11825                                         for (i = 0;i < 4;i++)
11826                                         {
11827                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11828                                                 f = DotProduct(right, v1) - l;
11829                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11830                                         }
11831                                 }
11832                         }
11833                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11834                         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);
11835                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11836                         rsurface.batchvertex3f_vertexbuffer = NULL;
11837                         rsurface.batchvertex3f_bufferoffset = 0;
11838                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11839                         rsurface.batchsvector3f_vertexbuffer = NULL;
11840                         rsurface.batchsvector3f_bufferoffset = 0;
11841                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11842                         rsurface.batchtvector3f_vertexbuffer = NULL;
11843                         rsurface.batchtvector3f_bufferoffset = 0;
11844                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11845                         rsurface.batchnormal3f_vertexbuffer = NULL;
11846                         rsurface.batchnormal3f_bufferoffset = 0;
11847                         break;
11848                 case Q3DEFORM_NORMAL:
11849                         // deform the normals to make reflections wavey
11850                         for (j = 0;j < rsurface.batchnumvertices;j++)
11851                         {
11852                                 float vertex[3];
11853                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11854                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11855                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11856                                 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]);
11857                                 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]);
11858                                 VectorNormalize(normal);
11859                         }
11860                         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);
11861                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11862                         rsurface.batchsvector3f_vertexbuffer = NULL;
11863                         rsurface.batchsvector3f_bufferoffset = 0;
11864                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11865                         rsurface.batchtvector3f_vertexbuffer = NULL;
11866                         rsurface.batchtvector3f_bufferoffset = 0;
11867                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11868                         rsurface.batchnormal3f_vertexbuffer = NULL;
11869                         rsurface.batchnormal3f_bufferoffset = 0;
11870                         break;
11871                 case Q3DEFORM_WAVE:
11872                         // deform vertex array to make wavey water and flags and such
11873                         waveparms[0] = deform->waveparms[0];
11874                         waveparms[1] = deform->waveparms[1];
11875                         waveparms[2] = deform->waveparms[2];
11876                         waveparms[3] = deform->waveparms[3];
11877                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11878                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11879                         // this is how a divisor of vertex influence on deformation
11880                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11881                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11882                         for (j = 0;j < rsurface.batchnumvertices;j++)
11883                         {
11884                                 // if the wavefunc depends on time, evaluate it per-vertex
11885                                 if (waveparms[3])
11886                                 {
11887                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11888                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11889                                 }
11890                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11891                         }
11892                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11893                         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);
11894                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11895                         rsurface.batchvertex3f_vertexbuffer = NULL;
11896                         rsurface.batchvertex3f_bufferoffset = 0;
11897                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11898                         rsurface.batchsvector3f_vertexbuffer = NULL;
11899                         rsurface.batchsvector3f_bufferoffset = 0;
11900                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11901                         rsurface.batchtvector3f_vertexbuffer = NULL;
11902                         rsurface.batchtvector3f_bufferoffset = 0;
11903                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11904                         rsurface.batchnormal3f_vertexbuffer = NULL;
11905                         rsurface.batchnormal3f_bufferoffset = 0;
11906                         break;
11907                 case Q3DEFORM_BULGE:
11908                         // deform vertex array to make the surface have moving bulges
11909                         for (j = 0;j < rsurface.batchnumvertices;j++)
11910                         {
11911                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11912                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11913                         }
11914                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11915                         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);
11916                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11917                         rsurface.batchvertex3f_vertexbuffer = NULL;
11918                         rsurface.batchvertex3f_bufferoffset = 0;
11919                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11920                         rsurface.batchsvector3f_vertexbuffer = NULL;
11921                         rsurface.batchsvector3f_bufferoffset = 0;
11922                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11923                         rsurface.batchtvector3f_vertexbuffer = NULL;
11924                         rsurface.batchtvector3f_bufferoffset = 0;
11925                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11926                         rsurface.batchnormal3f_vertexbuffer = NULL;
11927                         rsurface.batchnormal3f_bufferoffset = 0;
11928                         break;
11929                 case Q3DEFORM_MOVE:
11930                         // deform vertex array
11931                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11932                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11933                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11934                         VectorScale(deform->parms, scale, waveparms);
11935                         for (j = 0;j < rsurface.batchnumvertices;j++)
11936                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11937                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11938                         rsurface.batchvertex3f_vertexbuffer = NULL;
11939                         rsurface.batchvertex3f_bufferoffset = 0;
11940                         break;
11941                 }
11942         }
11943
11944         // generate texcoords based on the chosen texcoord source
11945         switch(rsurface.texture->tcgen.tcgen)
11946         {
11947         default:
11948         case Q3TCGEN_TEXTURE:
11949                 break;
11950         case Q3TCGEN_LIGHTMAP:
11951                 if (rsurface.batchtexcoordlightmap2f)
11952                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11953                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11954                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11955                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11956                 break;
11957         case Q3TCGEN_VECTOR:
11958                 for (j = 0;j < rsurface.batchnumvertices;j++)
11959                 {
11960                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11961                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11962                 }
11963                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11964                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11965                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11966                 break;
11967         case Q3TCGEN_ENVIRONMENT:
11968                 // make environment reflections using a spheremap
11969                 for (j = 0;j < rsurface.batchnumvertices;j++)
11970                 {
11971                         // identical to Q3A's method, but executed in worldspace so
11972                         // carried models can be shiny too
11973
11974                         float viewer[3], d, reflected[3], worldreflected[3];
11975
11976                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11977                         // VectorNormalize(viewer);
11978
11979                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11980
11981                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11982                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11983                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11984                         // note: this is proportinal to viewer, so we can normalize later
11985
11986                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11987                         VectorNormalize(worldreflected);
11988
11989                         // note: this sphere map only uses world x and z!
11990                         // so positive and negative y will LOOK THE SAME.
11991                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11992                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11993                 }
11994                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11995                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11996                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11997                 break;
11998         }
11999         // the only tcmod that needs software vertex processing is turbulent, so
12000         // check for it here and apply the changes if needed
12001         // and we only support that as the first one
12002         // (handling a mixture of turbulent and other tcmods would be problematic
12003         //  without punting it entirely to a software path)
12004         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12005         {
12006                 amplitude = rsurface.texture->tcmods[0].parms[1];
12007                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12008                 for (j = 0;j < rsurface.batchnumvertices;j++)
12009                 {
12010                         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);
12011                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12012                 }
12013                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12014                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12015                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12016         }
12017
12018         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12019         {
12020                 // convert the modified arrays to vertex structs
12021                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12022                 rsurface.batchvertexmeshbuffer = NULL;
12023                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12024                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12025                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12026                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12027                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12028                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12029                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12030                 {
12031                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12032                         {
12033                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12034                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12035                         }
12036                 }
12037                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12038                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12039                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12040                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12041                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12042                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12043                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12044                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12045                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12046         }
12047
12048         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12049         {
12050                 // convert the modified arrays to vertex structs
12051                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12052                 rsurface.batchvertexpositionbuffer = NULL;
12053                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12054                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12055                 else
12056                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12057                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12058         }
12059 }
12060
12061 void RSurf_DrawBatch(void)
12062 {
12063         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);
12064 }
12065
12066 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12067 {
12068         // pick the closest matching water plane
12069         int planeindex, vertexindex, bestplaneindex = -1;
12070         float d, bestd;
12071         vec3_t vert;
12072         const float *v;
12073         r_waterstate_waterplane_t *p;
12074         bestd = 0;
12075         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12076         {
12077                 if(p->camera_entity != rsurface.texture->camera_entity)
12078                         continue;
12079                 d = 0;
12080                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12081                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12082                 {
12083                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12084                         d += fabs(PlaneDiff(vert, &p->plane));
12085                 }
12086                 if (bestd > d || bestplaneindex < 0)
12087                 {
12088                         bestd = d;
12089                         bestplaneindex = planeindex;
12090                 }
12091         }
12092         return bestplaneindex;
12093 }
12094
12095 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12096 {
12097         int i;
12098         for (i = 0;i < rsurface.batchnumvertices;i++)
12099                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12100         rsurface.passcolor4f = rsurface.array_passcolor4f;
12101         rsurface.passcolor4f_vertexbuffer = 0;
12102         rsurface.passcolor4f_bufferoffset = 0;
12103 }
12104
12105 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12106 {
12107         int i;
12108         float f;
12109         const float *v;
12110         const float *c;
12111         float *c2;
12112         if (rsurface.passcolor4f)
12113         {
12114                 // generate color arrays
12115                 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)
12116                 {
12117                         f = RSurf_FogVertex(v);
12118                         c2[0] = c[0] * f;
12119                         c2[1] = c[1] * f;
12120                         c2[2] = c[2] * f;
12121                         c2[3] = c[3];
12122                 }
12123         }
12124         else
12125         {
12126                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12127                 {
12128                         f = RSurf_FogVertex(v);
12129                         c2[0] = f;
12130                         c2[1] = f;
12131                         c2[2] = f;
12132                         c2[3] = 1;
12133                 }
12134         }
12135         rsurface.passcolor4f = rsurface.array_passcolor4f;
12136         rsurface.passcolor4f_vertexbuffer = 0;
12137         rsurface.passcolor4f_bufferoffset = 0;
12138 }
12139
12140 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12141 {
12142         int i;
12143         float f;
12144         const float *v;
12145         const float *c;
12146         float *c2;
12147         if (!rsurface.passcolor4f)
12148                 return;
12149         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)
12150         {
12151                 f = RSurf_FogVertex(v);
12152                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12153                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12154                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12155                 c2[3] = c[3];
12156         }
12157         rsurface.passcolor4f = rsurface.array_passcolor4f;
12158         rsurface.passcolor4f_vertexbuffer = 0;
12159         rsurface.passcolor4f_bufferoffset = 0;
12160 }
12161
12162 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12163 {
12164         int i;
12165         const float *c;
12166         float *c2;
12167         if (!rsurface.passcolor4f)
12168                 return;
12169         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12170         {
12171                 c2[0] = c[0] * r;
12172                 c2[1] = c[1] * g;
12173                 c2[2] = c[2] * b;
12174                 c2[3] = c[3] * a;
12175         }
12176         rsurface.passcolor4f = rsurface.array_passcolor4f;
12177         rsurface.passcolor4f_vertexbuffer = 0;
12178         rsurface.passcolor4f_bufferoffset = 0;
12179 }
12180
12181 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12182 {
12183         int i;
12184         const float *c;
12185         float *c2;
12186         if (!rsurface.passcolor4f)
12187                 return;
12188         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12189         {
12190                 c2[0] = c[0] + r_refdef.scene.ambient;
12191                 c2[1] = c[1] + r_refdef.scene.ambient;
12192                 c2[2] = c[2] + r_refdef.scene.ambient;
12193                 c2[3] = c[3];
12194         }
12195         rsurface.passcolor4f = rsurface.array_passcolor4f;
12196         rsurface.passcolor4f_vertexbuffer = 0;
12197         rsurface.passcolor4f_bufferoffset = 0;
12198 }
12199
12200 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12201 {
12202         // TODO: optimize
12203         rsurface.passcolor4f = NULL;
12204         rsurface.passcolor4f_vertexbuffer = 0;
12205         rsurface.passcolor4f_bufferoffset = 0;
12206         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12207         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12208         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12209         GL_Color(r, g, b, a);
12210         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12211         RSurf_DrawBatch();
12212 }
12213
12214 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12215 {
12216         // TODO: optimize applyfog && applycolor case
12217         // just apply fog if necessary, and tint the fog color array if necessary
12218         rsurface.passcolor4f = NULL;
12219         rsurface.passcolor4f_vertexbuffer = 0;
12220         rsurface.passcolor4f_bufferoffset = 0;
12221         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12222         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12223         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12224         GL_Color(r, g, b, a);
12225         RSurf_DrawBatch();
12226 }
12227
12228 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12229 {
12230         // TODO: optimize
12231         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12232         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12233         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12234         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12235         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12236         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12237         GL_Color(r, g, b, a);
12238         RSurf_DrawBatch();
12239 }
12240
12241 static void RSurf_DrawBatch_GL11_ClampColor(void)
12242 {
12243         int i;
12244         const float *c1;
12245         float *c2;
12246         if (!rsurface.passcolor4f)
12247                 return;
12248         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12249         {
12250                 c2[0] = bound(0.0f, c1[0], 1.0f);
12251                 c2[1] = bound(0.0f, c1[1], 1.0f);
12252                 c2[2] = bound(0.0f, c1[2], 1.0f);
12253                 c2[3] = bound(0.0f, c1[3], 1.0f);
12254         }
12255 }
12256
12257 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12258 {
12259         int i;
12260         float f;
12261         float alpha;
12262         const float *v;
12263         const float *n;
12264         float *c;
12265         vec3_t ambientcolor;
12266         vec3_t diffusecolor;
12267         vec3_t lightdir;
12268         // TODO: optimize
12269         // model lighting
12270         VectorCopy(rsurface.modellight_lightdir, lightdir);
12271         f = 0.5f * r_refdef.lightmapintensity;
12272         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12273         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12274         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12275         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12276         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12277         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12278         alpha = *a;
12279         if (VectorLength2(diffusecolor) > 0)
12280         {
12281                 // q3-style directional shading
12282                 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)
12283                 {
12284                         if ((f = DotProduct(n, lightdir)) > 0)
12285                                 VectorMA(ambientcolor, f, diffusecolor, c);
12286                         else
12287                                 VectorCopy(ambientcolor, c);
12288                         c[3] = alpha;
12289                 }
12290                 *r = 1;
12291                 *g = 1;
12292                 *b = 1;
12293                 *a = 1;
12294                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12295                 rsurface.passcolor4f_vertexbuffer = 0;
12296                 rsurface.passcolor4f_bufferoffset = 0;
12297                 *applycolor = false;
12298         }
12299         else
12300         {
12301                 *r = ambientcolor[0];
12302                 *g = ambientcolor[1];
12303                 *b = ambientcolor[2];
12304                 rsurface.passcolor4f = NULL;
12305                 rsurface.passcolor4f_vertexbuffer = 0;
12306                 rsurface.passcolor4f_bufferoffset = 0;
12307         }
12308 }
12309
12310 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12311 {
12312         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12313         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12314         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12315         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12316         GL_Color(r, g, b, a);
12317         RSurf_DrawBatch();
12318 }
12319
12320 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12321 {
12322         int i;
12323         float f;
12324         const float *v;
12325         float *c;
12326         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12327         {
12328                 f = 1 - RSurf_FogVertex(v);
12329                 c[0] = r;
12330                 c[1] = g;
12331                 c[2] = b;
12332                 c[3] = f * a;
12333         }
12334 }
12335
12336 void RSurf_SetupDepthAndCulling(void)
12337 {
12338         // submodels are biased to avoid z-fighting with world surfaces that they
12339         // may be exactly overlapping (avoids z-fighting artifacts on certain
12340         // doors and things in Quake maps)
12341         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12342         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12343         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12344         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12345 }
12346
12347 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12348 {
12349         // transparent sky would be ridiculous
12350         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12351                 return;
12352         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12353         skyrenderlater = true;
12354         RSurf_SetupDepthAndCulling();
12355         GL_DepthMask(true);
12356         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12357         // skymasking on them, and Quake3 never did sky masking (unlike
12358         // software Quake and software Quake2), so disable the sky masking
12359         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12360         // and skymasking also looks very bad when noclipping outside the
12361         // level, so don't use it then either.
12362         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12363         {
12364                 R_Mesh_ResetTextureState();
12365                 if (skyrendermasked)
12366                 {
12367                         R_SetupShader_DepthOrShadow();
12368                         // depth-only (masking)
12369                         GL_ColorMask(0,0,0,0);
12370                         // just to make sure that braindead drivers don't draw
12371                         // anything despite that colormask...
12372                         GL_BlendFunc(GL_ZERO, GL_ONE);
12373                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12374                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12375                 }
12376                 else
12377                 {
12378                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12379                         // fog sky
12380                         GL_BlendFunc(GL_ONE, GL_ZERO);
12381                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12382                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12383                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12384                 }
12385                 RSurf_DrawBatch();
12386                 if (skyrendermasked)
12387                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12388         }
12389         R_Mesh_ResetTextureState();
12390         GL_Color(1, 1, 1, 1);
12391 }
12392
12393 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12394 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12395 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12396 {
12397         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12398                 return;
12399         if (prepass)
12400         {
12401                 // render screenspace normalmap to texture
12402                 GL_DepthMask(true);
12403                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12404                 RSurf_DrawBatch();
12405                 return;
12406         }
12407
12408         // bind lightmap texture
12409
12410         // water/refraction/reflection/camera surfaces have to be handled specially
12411         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12412         {
12413                 int start, end, startplaneindex;
12414                 for (start = 0;start < texturenumsurfaces;start = end)
12415                 {
12416                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12417                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12418                                 ;
12419                         // now that we have a batch using the same planeindex, render it
12420                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12421                         {
12422                                 // render water or distortion background
12423                                 GL_DepthMask(true);
12424                                 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));
12425                                 RSurf_DrawBatch();
12426                                 // blend surface on top
12427                                 GL_DepthMask(false);
12428                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12429                                 RSurf_DrawBatch();
12430                         }
12431                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12432                         {
12433                                 // render surface with reflection texture as input
12434                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12435                                 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));
12436                                 RSurf_DrawBatch();
12437                         }
12438                 }
12439                 return;
12440         }
12441
12442         // render surface batch normally
12443         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12444         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12445         RSurf_DrawBatch();
12446 }
12447
12448 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12449 {
12450         // OpenGL 1.3 path - anything not completely ancient
12451         qboolean applycolor;
12452         qboolean applyfog;
12453         int layerindex;
12454         const texturelayer_t *layer;
12455         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);
12456         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12457
12458         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12459         {
12460                 vec4_t layercolor;
12461                 int layertexrgbscale;
12462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12463                 {
12464                         if (layerindex == 0)
12465                                 GL_AlphaTest(true);
12466                         else
12467                         {
12468                                 GL_AlphaTest(false);
12469                                 GL_DepthFunc(GL_EQUAL);
12470                         }
12471                 }
12472                 GL_DepthMask(layer->depthmask && writedepth);
12473                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12474                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12475                 {
12476                         layertexrgbscale = 4;
12477                         VectorScale(layer->color, 0.25f, layercolor);
12478                 }
12479                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12480                 {
12481                         layertexrgbscale = 2;
12482                         VectorScale(layer->color, 0.5f, layercolor);
12483                 }
12484                 else
12485                 {
12486                         layertexrgbscale = 1;
12487                         VectorScale(layer->color, 1.0f, layercolor);
12488                 }
12489                 layercolor[3] = layer->color[3];
12490                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12491                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12492                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12493                 switch (layer->type)
12494                 {
12495                 case TEXTURELAYERTYPE_LITTEXTURE:
12496                         // single-pass lightmapped texture with 2x rgbscale
12497                         R_Mesh_TexBind(0, r_texture_white);
12498                         R_Mesh_TexMatrix(0, NULL);
12499                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12500                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12501                         R_Mesh_TexBind(1, layer->texture);
12502                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12503                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12504                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12505                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12506                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12507                         else if (rsurface.uselightmaptexture)
12508                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12509                         else
12510                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12511                         break;
12512                 case TEXTURELAYERTYPE_TEXTURE:
12513                         // singletexture unlit texture with transparency support
12514                         R_Mesh_TexBind(0, layer->texture);
12515                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12516                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12517                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12518                         R_Mesh_TexBind(1, 0);
12519                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12520                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12521                         break;
12522                 case TEXTURELAYERTYPE_FOG:
12523                         // singletexture fogging
12524                         if (layer->texture)
12525                         {
12526                                 R_Mesh_TexBind(0, layer->texture);
12527                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12528                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12529                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12530                         }
12531                         else
12532                         {
12533                                 R_Mesh_TexBind(0, 0);
12534                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12535                         }
12536                         R_Mesh_TexBind(1, 0);
12537                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12538                         // generate a color array for the fog pass
12539                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12540                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12541                         RSurf_DrawBatch();
12542                         break;
12543                 default:
12544                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12545                 }
12546         }
12547         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12548         {
12549                 GL_DepthFunc(GL_LEQUAL);
12550                 GL_AlphaTest(false);
12551         }
12552 }
12553
12554 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12555 {
12556         // OpenGL 1.1 - crusty old voodoo path
12557         qboolean applyfog;
12558         int layerindex;
12559         const texturelayer_t *layer;
12560         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);
12561         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12562
12563         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12564         {
12565                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12566                 {
12567                         if (layerindex == 0)
12568                                 GL_AlphaTest(true);
12569                         else
12570                         {
12571                                 GL_AlphaTest(false);
12572                                 GL_DepthFunc(GL_EQUAL);
12573                         }
12574                 }
12575                 GL_DepthMask(layer->depthmask && writedepth);
12576                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12577                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12578                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12579                 switch (layer->type)
12580                 {
12581                 case TEXTURELAYERTYPE_LITTEXTURE:
12582                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12583                         {
12584                                 // two-pass lit texture with 2x rgbscale
12585                                 // first the lightmap pass
12586                                 R_Mesh_TexBind(0, r_texture_white);
12587                                 R_Mesh_TexMatrix(0, NULL);
12588                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12589                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12590                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12591                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12592                                 else if (rsurface.uselightmaptexture)
12593                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12594                                 else
12595                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12596                                 // then apply the texture to it
12597                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12598                                 R_Mesh_TexBind(0, layer->texture);
12599                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12600                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12601                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12602                                 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);
12603                         }
12604                         else
12605                         {
12606                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12607                                 R_Mesh_TexBind(0, layer->texture);
12608                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12609                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12610                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12611                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12612                                         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);
12613                                 else
12614                                         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);
12615                         }
12616                         break;
12617                 case TEXTURELAYERTYPE_TEXTURE:
12618                         // singletexture unlit texture with transparency support
12619                         R_Mesh_TexBind(0, layer->texture);
12620                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12621                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12622                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12623                         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);
12624                         break;
12625                 case TEXTURELAYERTYPE_FOG:
12626                         // singletexture fogging
12627                         if (layer->texture)
12628                         {
12629                                 R_Mesh_TexBind(0, layer->texture);
12630                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12631                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12632                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12633                         }
12634                         else
12635                         {
12636                                 R_Mesh_TexBind(0, 0);
12637                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12638                         }
12639                         // generate a color array for the fog pass
12640                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12641                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12642                         RSurf_DrawBatch();
12643                         break;
12644                 default:
12645                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12646                 }
12647         }
12648         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12649         {
12650                 GL_DepthFunc(GL_LEQUAL);
12651                 GL_AlphaTest(false);
12652         }
12653 }
12654
12655 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12656 {
12657         int vi;
12658         int j;
12659         r_vertexgeneric_t *batchvertex;
12660         float c[4];
12661
12662         GL_AlphaTest(false);
12663         R_Mesh_ResetTextureState();
12664         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12665
12666         if(rsurface.texture && rsurface.texture->currentskinframe)
12667         {
12668                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12669                 c[3] *= rsurface.texture->currentalpha;
12670         }
12671         else
12672         {
12673                 c[0] = 1;
12674                 c[1] = 0;
12675                 c[2] = 1;
12676                 c[3] = 1;
12677         }
12678
12679         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12680         {
12681                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12682                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12683                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12684         }
12685
12686         // brighten it up (as texture value 127 means "unlit")
12687         c[0] *= 2 * r_refdef.view.colorscale;
12688         c[1] *= 2 * r_refdef.view.colorscale;
12689         c[2] *= 2 * r_refdef.view.colorscale;
12690
12691         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12692                 c[3] *= r_wateralpha.value;
12693
12694         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12695         {
12696                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12697                 GL_DepthMask(false);
12698         }
12699         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12700         {
12701                 GL_BlendFunc(GL_ONE, GL_ONE);
12702                 GL_DepthMask(false);
12703         }
12704         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12705         {
12706                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12707                 GL_DepthMask(false);
12708         }
12709         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12710         {
12711                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12712                 GL_DepthMask(false);
12713         }
12714         else
12715         {
12716                 GL_BlendFunc(GL_ONE, GL_ZERO);
12717                 GL_DepthMask(writedepth);
12718         }
12719
12720         if (r_showsurfaces.integer == 3)
12721         {
12722                 rsurface.passcolor4f = NULL;
12723
12724                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12725                 {
12726                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12727
12728                         rsurface.passcolor4f = NULL;
12729                         rsurface.passcolor4f_vertexbuffer = 0;
12730                         rsurface.passcolor4f_bufferoffset = 0;
12731                 }
12732                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12733                 {
12734                         qboolean applycolor = true;
12735                         float one = 1.0;
12736
12737                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12738
12739                         r_refdef.lightmapintensity = 1;
12740                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12741                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12742                 }
12743                 else
12744                 {
12745                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12746
12747                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12748                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12749                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12750                 }
12751
12752                 if(!rsurface.passcolor4f)
12753                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12754
12755                 RSurf_DrawBatch_GL11_ApplyAmbient();
12756                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12757                 if(r_refdef.fogenabled)
12758                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12759                 RSurf_DrawBatch_GL11_ClampColor();
12760
12761                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12762                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12763                 RSurf_DrawBatch();
12764         }
12765         else if (!r_refdef.view.showdebug)
12766         {
12767                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12768                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12769                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12770                 {
12771                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12772                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12773                 }
12774                 R_Mesh_PrepareVertices_Generic_Unlock();
12775                 RSurf_DrawBatch();
12776         }
12777         else if (r_showsurfaces.integer == 4)
12778         {
12779                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12780                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12781                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12782                 {
12783                         unsigned char c = vi << 3;
12784                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12785                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12786                 }
12787                 R_Mesh_PrepareVertices_Generic_Unlock();
12788                 RSurf_DrawBatch();
12789         }
12790         else if (r_showsurfaces.integer == 2)
12791         {
12792                 const int *e;
12793                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12794                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12795                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12796                 {
12797                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12798                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12799                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12800                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12801                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12802                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12803                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12804                 }
12805                 R_Mesh_PrepareVertices_Generic_Unlock();
12806                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12807         }
12808         else
12809         {
12810                 int texturesurfaceindex;
12811                 int k;
12812                 const msurface_t *surface;
12813                 unsigned char surfacecolor4ub[4];
12814                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12815                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12816                 vi = 0;
12817                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12818                 {
12819                         surface = texturesurfacelist[texturesurfaceindex];
12820                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12821                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12822                         for (j = 0;j < surface->num_vertices;j++)
12823                         {
12824                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12825                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12826                                 vi++;
12827                         }
12828                 }
12829                 R_Mesh_PrepareVertices_Generic_Unlock();
12830                 RSurf_DrawBatch();
12831         }
12832 }
12833
12834 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12835 {
12836         CHECKGLERROR
12837         RSurf_SetupDepthAndCulling();
12838         if (r_showsurfaces.integer)
12839         {
12840                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12841                 return;
12842         }
12843         switch (vid.renderpath)
12844         {
12845         case RENDERPATH_GL20:
12846         case RENDERPATH_CGGL:
12847         case RENDERPATH_D3D9:
12848         case RENDERPATH_D3D10:
12849         case RENDERPATH_D3D11:
12850                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12851                 break;
12852         case RENDERPATH_GL13:
12853                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12854                 break;
12855         case RENDERPATH_GL11:
12856                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12857                 break;
12858         }
12859         CHECKGLERROR
12860 }
12861
12862 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12863 {
12864         CHECKGLERROR
12865         RSurf_SetupDepthAndCulling();
12866         if (r_showsurfaces.integer)
12867         {
12868                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12869                 return;
12870         }
12871         switch (vid.renderpath)
12872         {
12873         case RENDERPATH_GL20:
12874         case RENDERPATH_CGGL:
12875         case RENDERPATH_D3D9:
12876         case RENDERPATH_D3D10:
12877         case RENDERPATH_D3D11:
12878                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12879                 break;
12880         case RENDERPATH_GL13:
12881                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12882                 break;
12883         case RENDERPATH_GL11:
12884                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12885                 break;
12886         }
12887         CHECKGLERROR
12888 }
12889
12890 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12891 {
12892         int i, j;
12893         int texturenumsurfaces, endsurface;
12894         texture_t *texture;
12895         const msurface_t *surface;
12896 #define MAXBATCH_TRANSPARENTSURFACES 256
12897         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12898
12899         // if the model is static it doesn't matter what value we give for
12900         // wantnormals and wanttangents, so this logic uses only rules applicable
12901         // to a model, knowing that they are meaningless otherwise
12902         if (ent == r_refdef.scene.worldentity)
12903                 RSurf_ActiveWorldEntity();
12904         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12905                 RSurf_ActiveModelEntity(ent, false, false, false);
12906         else
12907         {
12908                 switch (vid.renderpath)
12909                 {
12910                 case RENDERPATH_GL20:
12911                 case RENDERPATH_CGGL:
12912                 case RENDERPATH_D3D9:
12913                 case RENDERPATH_D3D10:
12914                 case RENDERPATH_D3D11:
12915                         RSurf_ActiveModelEntity(ent, true, true, false);
12916                         break;
12917                 case RENDERPATH_GL13:
12918                 case RENDERPATH_GL11:
12919                         RSurf_ActiveModelEntity(ent, true, false, false);
12920                         break;
12921                 }
12922         }
12923
12924         if (r_transparentdepthmasking.integer)
12925         {
12926                 qboolean setup = false;
12927                 for (i = 0;i < numsurfaces;i = j)
12928                 {
12929                         j = i + 1;
12930                         surface = rsurface.modelsurfaces + surfacelist[i];
12931                         texture = surface->texture;
12932                         rsurface.texture = R_GetCurrentTexture(texture);
12933                         rsurface.lightmaptexture = NULL;
12934                         rsurface.deluxemaptexture = NULL;
12935                         rsurface.uselightmaptexture = false;
12936                         // scan ahead until we find a different texture
12937                         endsurface = min(i + 1024, numsurfaces);
12938                         texturenumsurfaces = 0;
12939                         texturesurfacelist[texturenumsurfaces++] = surface;
12940                         for (;j < endsurface;j++)
12941                         {
12942                                 surface = rsurface.modelsurfaces + surfacelist[j];
12943                                 if (texture != surface->texture)
12944                                         break;
12945                                 texturesurfacelist[texturenumsurfaces++] = surface;
12946                         }
12947                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12948                                 continue;
12949                         // render the range of surfaces as depth
12950                         if (!setup)
12951                         {
12952                                 setup = true;
12953                                 GL_ColorMask(0,0,0,0);
12954                                 GL_Color(1,1,1,1);
12955                                 GL_DepthTest(true);
12956                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12957                                 GL_DepthMask(true);
12958                                 GL_AlphaTest(false);
12959                                 R_Mesh_ResetTextureState();
12960                                 R_SetupShader_DepthOrShadow();
12961                         }
12962                         RSurf_SetupDepthAndCulling();
12963                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12964                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12965                         RSurf_DrawBatch();
12966                 }
12967                 if (setup)
12968                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12969         }
12970
12971         for (i = 0;i < numsurfaces;i = j)
12972         {
12973                 j = i + 1;
12974                 surface = rsurface.modelsurfaces + surfacelist[i];
12975                 texture = surface->texture;
12976                 rsurface.texture = R_GetCurrentTexture(texture);
12977                 rsurface.lightmaptexture = surface->lightmaptexture;
12978                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12979                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12980                 // scan ahead until we find a different texture
12981                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12982                 texturenumsurfaces = 0;
12983                 texturesurfacelist[texturenumsurfaces++] = surface;
12984                 for (;j < endsurface;j++)
12985                 {
12986                         surface = rsurface.modelsurfaces + surfacelist[j];
12987                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12988                                 break;
12989                         texturesurfacelist[texturenumsurfaces++] = surface;
12990                 }
12991                 // render the range of surfaces
12992                 if (ent == r_refdef.scene.worldentity)
12993                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12994                 else
12995                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12996         }
12997         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12998         GL_AlphaTest(false);
12999 }
13000
13001 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13002 {
13003         // transparent surfaces get pushed off into the transparent queue
13004         int surfacelistindex;
13005         const msurface_t *surface;
13006         vec3_t tempcenter, center;
13007         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13008         {
13009                 surface = texturesurfacelist[surfacelistindex];
13010                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13011                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13012                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13013                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13014                 if (queueentity->transparent_offset) // transparent offset
13015                 {
13016                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13017                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13018                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13019                 }
13020                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13021         }
13022 }
13023
13024 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13025 {
13026         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13027                 return;
13028         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13029                 return;
13030         RSurf_SetupDepthAndCulling();
13031         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13032         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13033         RSurf_DrawBatch();
13034 }
13035
13036 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13037 {
13038         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13039         CHECKGLERROR
13040         if (depthonly)
13041                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13042         else if (prepass)
13043         {
13044                 if (!rsurface.texture->currentnumlayers)
13045                         return;
13046                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13047                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13048                 else
13049                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13050         }
13051         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13052                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13053         else if (!rsurface.texture->currentnumlayers)
13054                 return;
13055         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13056         {
13057                 // in the deferred case, transparent surfaces were queued during prepass
13058                 if (!r_shadow_usingdeferredprepass)
13059                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13060         }
13061         else
13062         {
13063                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13064                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13065         }
13066         CHECKGLERROR
13067 }
13068
13069 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13070 {
13071         int i, j;
13072         texture_t *texture;
13073         // break the surface list down into batches by texture and use of lightmapping
13074         for (i = 0;i < numsurfaces;i = j)
13075         {
13076                 j = i + 1;
13077                 // texture is the base texture pointer, rsurface.texture is the
13078                 // current frame/skin the texture is directing us to use (for example
13079                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13080                 // use skin 1 instead)
13081                 texture = surfacelist[i]->texture;
13082                 rsurface.texture = R_GetCurrentTexture(texture);
13083                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13084                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13085                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13086                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13087                 {
13088                         // if this texture is not the kind we want, skip ahead to the next one
13089                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13090                                 ;
13091                         continue;
13092                 }
13093                 // simply scan ahead until we find a different texture or lightmap state
13094                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13095                         ;
13096                 // render the range of surfaces
13097                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13098         }
13099 }
13100
13101 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13102 {
13103         CHECKGLERROR
13104         if (depthonly)
13105                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13106         else if (prepass)
13107         {
13108                 if (!rsurface.texture->currentnumlayers)
13109                         return;
13110                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13111                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13112                 else
13113                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13114         }
13115         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13116                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13117         else if (!rsurface.texture->currentnumlayers)
13118                 return;
13119         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13120         {
13121                 // in the deferred case, transparent surfaces were queued during prepass
13122                 if (!r_shadow_usingdeferredprepass)
13123                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13124         }
13125         else
13126         {
13127                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13128                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13129         }
13130         CHECKGLERROR
13131 }
13132
13133 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13134 {
13135         int i, j;
13136         texture_t *texture;
13137         // break the surface list down into batches by texture and use of lightmapping
13138         for (i = 0;i < numsurfaces;i = j)
13139         {
13140                 j = i + 1;
13141                 // texture is the base texture pointer, rsurface.texture is the
13142                 // current frame/skin the texture is directing us to use (for example
13143                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13144                 // use skin 1 instead)
13145                 texture = surfacelist[i]->texture;
13146                 rsurface.texture = R_GetCurrentTexture(texture);
13147                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13148                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13149                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13150                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13151                 {
13152                         // if this texture is not the kind we want, skip ahead to the next one
13153                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13154                                 ;
13155                         continue;
13156                 }
13157                 // simply scan ahead until we find a different texture or lightmap state
13158                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13159                         ;
13160                 // render the range of surfaces
13161                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13162         }
13163 }
13164
13165 float locboxvertex3f[6*4*3] =
13166 {
13167         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13168         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13169         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13170         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13171         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13172         1,0,0, 0,0,0, 0,1,0, 1,1,0
13173 };
13174
13175 unsigned short locboxelements[6*2*3] =
13176 {
13177          0, 1, 2, 0, 2, 3,
13178          4, 5, 6, 4, 6, 7,
13179          8, 9,10, 8,10,11,
13180         12,13,14, 12,14,15,
13181         16,17,18, 16,18,19,
13182         20,21,22, 20,22,23
13183 };
13184
13185 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13186 {
13187         int i, j;
13188         cl_locnode_t *loc = (cl_locnode_t *)ent;
13189         vec3_t mins, size;
13190         float vertex3f[6*4*3];
13191         CHECKGLERROR
13192         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13193         GL_DepthMask(false);
13194         GL_DepthRange(0, 1);
13195         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13196         GL_DepthTest(true);
13197         GL_CullFace(GL_NONE);
13198         R_EntityMatrix(&identitymatrix);
13199
13200         R_Mesh_ResetTextureState();
13201
13202         i = surfacelist[0];
13203         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13204                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13205                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13206                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13207
13208         if (VectorCompare(loc->mins, loc->maxs))
13209         {
13210                 VectorSet(size, 2, 2, 2);
13211                 VectorMA(loc->mins, -0.5f, size, mins);
13212         }
13213         else
13214         {
13215                 VectorCopy(loc->mins, mins);
13216                 VectorSubtract(loc->maxs, loc->mins, size);
13217         }
13218
13219         for (i = 0;i < 6*4*3;)
13220                 for (j = 0;j < 3;j++, i++)
13221                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13222
13223         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13224         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13225         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13226 }
13227
13228 void R_DrawLocs(void)
13229 {
13230         int index;
13231         cl_locnode_t *loc, *nearestloc;
13232         vec3_t center;
13233         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13234         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13235         {
13236                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13237                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13238         }
13239 }
13240
13241 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13242 {
13243         if (decalsystem->decals)
13244                 Mem_Free(decalsystem->decals);
13245         memset(decalsystem, 0, sizeof(*decalsystem));
13246 }
13247
13248 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)
13249 {
13250         tridecal_t *decal;
13251         tridecal_t *decals;
13252         int i;
13253
13254         // expand or initialize the system
13255         if (decalsystem->maxdecals <= decalsystem->numdecals)
13256         {
13257                 decalsystem_t old = *decalsystem;
13258                 qboolean useshortelements;
13259                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13260                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13261                 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)));
13262                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13263                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13264                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13265                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13266                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13267                 if (decalsystem->numdecals)
13268                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13269                 if (old.decals)
13270                         Mem_Free(old.decals);
13271                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13272                         decalsystem->element3i[i] = i;
13273                 if (useshortelements)
13274                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13275                                 decalsystem->element3s[i] = i;
13276         }
13277
13278         // grab a decal and search for another free slot for the next one
13279         decals = decalsystem->decals;
13280         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13281         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13282                 ;
13283         decalsystem->freedecal = i;
13284         if (decalsystem->numdecals <= i)
13285                 decalsystem->numdecals = i + 1;
13286
13287         // initialize the decal
13288         decal->lived = 0;
13289         decal->triangleindex = triangleindex;
13290         decal->surfaceindex = surfaceindex;
13291         decal->decalsequence = decalsequence;
13292         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13293         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13294         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13295         decal->color4ub[0][3] = 255;
13296         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13297         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13298         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13299         decal->color4ub[1][3] = 255;
13300         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13301         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13302         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13303         decal->color4ub[2][3] = 255;
13304         decal->vertex3f[0][0] = v0[0];
13305         decal->vertex3f[0][1] = v0[1];
13306         decal->vertex3f[0][2] = v0[2];
13307         decal->vertex3f[1][0] = v1[0];
13308         decal->vertex3f[1][1] = v1[1];
13309         decal->vertex3f[1][2] = v1[2];
13310         decal->vertex3f[2][0] = v2[0];
13311         decal->vertex3f[2][1] = v2[1];
13312         decal->vertex3f[2][2] = v2[2];
13313         decal->texcoord2f[0][0] = t0[0];
13314         decal->texcoord2f[0][1] = t0[1];
13315         decal->texcoord2f[1][0] = t1[0];
13316         decal->texcoord2f[1][1] = t1[1];
13317         decal->texcoord2f[2][0] = t2[0];
13318         decal->texcoord2f[2][1] = t2[1];
13319 }
13320
13321 extern cvar_t cl_decals_bias;
13322 extern cvar_t cl_decals_models;
13323 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13324 // baseparms, parms, temps
13325 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)
13326 {
13327         int cornerindex;
13328         int index;
13329         float v[9][3];
13330         const float *vertex3f;
13331         int numpoints;
13332         float points[2][9][3];
13333         float temp[3];
13334         float tc[9][2];
13335         float f;
13336         float c[9][4];
13337         const int *e;
13338
13339         e = rsurface.modelelement3i + 3*triangleindex;
13340
13341         vertex3f = rsurface.modelvertex3f;
13342
13343         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13344         {
13345                 index = 3*e[cornerindex];
13346                 VectorCopy(vertex3f + index, v[cornerindex]);
13347         }
13348         // cull backfaces
13349         //TriangleNormal(v[0], v[1], v[2], normal);
13350         //if (DotProduct(normal, localnormal) < 0.0f)
13351         //      continue;
13352         // clip by each of the box planes formed from the projection matrix
13353         // if anything survives, we emit the decal
13354         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]);
13355         if (numpoints < 3)
13356                 return;
13357         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]);
13358         if (numpoints < 3)
13359                 return;
13360         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]);
13361         if (numpoints < 3)
13362                 return;
13363         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]);
13364         if (numpoints < 3)
13365                 return;
13366         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]);
13367         if (numpoints < 3)
13368                 return;
13369         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]);
13370         if (numpoints < 3)
13371                 return;
13372         // some part of the triangle survived, so we have to accept it...
13373         if (dynamic)
13374         {
13375                 // dynamic always uses the original triangle
13376                 numpoints = 3;
13377                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13378                 {
13379                         index = 3*e[cornerindex];
13380                         VectorCopy(vertex3f + index, v[cornerindex]);
13381                 }
13382         }
13383         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13384         {
13385                 // convert vertex positions to texcoords
13386                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13387                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13388                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13389                 // calculate distance fade from the projection origin
13390                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13391                 f = bound(0.0f, f, 1.0f);
13392                 c[cornerindex][0] = r * f;
13393                 c[cornerindex][1] = g * f;
13394                 c[cornerindex][2] = b * f;
13395                 c[cornerindex][3] = 1.0f;
13396                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13397         }
13398         if (dynamic)
13399                 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);
13400         else
13401                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13402                         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);
13403 }
13404 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)
13405 {
13406         matrix4x4_t projection;
13407         decalsystem_t *decalsystem;
13408         qboolean dynamic;
13409         dp_model_t *model;
13410         const msurface_t *surface;
13411         const msurface_t *surfaces;
13412         const int *surfacelist;
13413         const texture_t *texture;
13414         int numtriangles;
13415         int numsurfacelist;
13416         int surfacelistindex;
13417         int surfaceindex;
13418         int triangleindex;
13419         float localorigin[3];
13420         float localnormal[3];
13421         float localmins[3];
13422         float localmaxs[3];
13423         float localsize;
13424         //float normal[3];
13425         float planes[6][4];
13426         float angles[3];
13427         bih_t *bih;
13428         int bih_triangles_count;
13429         int bih_triangles[256];
13430         int bih_surfaces[256];
13431
13432         decalsystem = &ent->decalsystem;
13433         model = ent->model;
13434         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13435         {
13436                 R_DecalSystem_Reset(&ent->decalsystem);
13437                 return;
13438         }
13439
13440         if (!model->brush.data_leafs && !cl_decals_models.integer)
13441         {
13442                 if (decalsystem->model)
13443                         R_DecalSystem_Reset(decalsystem);
13444                 return;
13445         }
13446
13447         if (decalsystem->model != model)
13448                 R_DecalSystem_Reset(decalsystem);
13449         decalsystem->model = model;
13450
13451         RSurf_ActiveModelEntity(ent, false, false, false);
13452
13453         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13454         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13455         VectorNormalize(localnormal);
13456         localsize = worldsize*rsurface.inversematrixscale;
13457         localmins[0] = localorigin[0] - localsize;
13458         localmins[1] = localorigin[1] - localsize;
13459         localmins[2] = localorigin[2] - localsize;
13460         localmaxs[0] = localorigin[0] + localsize;
13461         localmaxs[1] = localorigin[1] + localsize;
13462         localmaxs[2] = localorigin[2] + localsize;
13463
13464         //VectorCopy(localnormal, planes[4]);
13465         //VectorVectors(planes[4], planes[2], planes[0]);
13466         AnglesFromVectors(angles, localnormal, NULL, false);
13467         AngleVectors(angles, planes[0], planes[2], planes[4]);
13468         VectorNegate(planes[0], planes[1]);
13469         VectorNegate(planes[2], planes[3]);
13470         VectorNegate(planes[4], planes[5]);
13471         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13472         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13473         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13474         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13475         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13476         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13477
13478 #if 1
13479 // works
13480 {
13481         matrix4x4_t forwardprojection;
13482         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13483         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13484 }
13485 #else
13486 // broken
13487 {
13488         float projectionvector[4][3];
13489         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13490         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13491         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13492         projectionvector[0][0] = planes[0][0] * ilocalsize;
13493         projectionvector[0][1] = planes[1][0] * ilocalsize;
13494         projectionvector[0][2] = planes[2][0] * ilocalsize;
13495         projectionvector[1][0] = planes[0][1] * ilocalsize;
13496         projectionvector[1][1] = planes[1][1] * ilocalsize;
13497         projectionvector[1][2] = planes[2][1] * ilocalsize;
13498         projectionvector[2][0] = planes[0][2] * ilocalsize;
13499         projectionvector[2][1] = planes[1][2] * ilocalsize;
13500         projectionvector[2][2] = planes[2][2] * ilocalsize;
13501         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13502         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13503         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13504         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13505 }
13506 #endif
13507
13508         dynamic = model->surfmesh.isanimated;
13509         numsurfacelist = model->nummodelsurfaces;
13510         surfacelist = model->sortedmodelsurfaces;
13511         surfaces = model->data_surfaces;
13512
13513         bih = NULL;
13514         bih_triangles_count = -1;
13515         if(!dynamic)
13516         {
13517                 if(model->render_bih.numleafs)
13518                         bih = &model->render_bih;
13519                 else if(model->collision_bih.numleafs)
13520                         bih = &model->collision_bih;
13521         }
13522         if(bih)
13523                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13524         if(bih_triangles_count == 0)
13525                 return;
13526         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13527                 return;
13528         if(bih_triangles_count > 0)
13529         {
13530                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13531                 {
13532                         surfaceindex = bih_surfaces[triangleindex];
13533                         surface = surfaces + surfaceindex;
13534                         texture = surface->texture;
13535                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13536                                 continue;
13537                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13538                                 continue;
13539                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13540                 }
13541         }
13542         else
13543         {
13544                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13545                 {
13546                         surfaceindex = surfacelist[surfacelistindex];
13547                         surface = surfaces + surfaceindex;
13548                         // check cull box first because it rejects more than any other check
13549                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13550                                 continue;
13551                         // skip transparent surfaces
13552                         texture = surface->texture;
13553                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13554                                 continue;
13555                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13556                                 continue;
13557                         numtriangles = surface->num_triangles;
13558                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13559                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13560                 }
13561         }
13562 }
13563
13564 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13565 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)
13566 {
13567         int renderentityindex;
13568         float worldmins[3];
13569         float worldmaxs[3];
13570         entity_render_t *ent;
13571
13572         if (!cl_decals_newsystem.integer)
13573                 return;
13574
13575         worldmins[0] = worldorigin[0] - worldsize;
13576         worldmins[1] = worldorigin[1] - worldsize;
13577         worldmins[2] = worldorigin[2] - worldsize;
13578         worldmaxs[0] = worldorigin[0] + worldsize;
13579         worldmaxs[1] = worldorigin[1] + worldsize;
13580         worldmaxs[2] = worldorigin[2] + worldsize;
13581
13582         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13583
13584         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13585         {
13586                 ent = r_refdef.scene.entities[renderentityindex];
13587                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13588                         continue;
13589
13590                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13591         }
13592 }
13593
13594 typedef struct r_decalsystem_splatqueue_s
13595 {
13596         vec3_t worldorigin;
13597         vec3_t worldnormal;
13598         float color[4];
13599         float tcrange[4];
13600         float worldsize;
13601         int decalsequence;
13602 }
13603 r_decalsystem_splatqueue_t;
13604
13605 int r_decalsystem_numqueued = 0;
13606 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13607
13608 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)
13609 {
13610         r_decalsystem_splatqueue_t *queue;
13611
13612         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13613                 return;
13614
13615         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13616         VectorCopy(worldorigin, queue->worldorigin);
13617         VectorCopy(worldnormal, queue->worldnormal);
13618         Vector4Set(queue->color, r, g, b, a);
13619         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13620         queue->worldsize = worldsize;
13621         queue->decalsequence = cl.decalsequence++;
13622 }
13623
13624 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13625 {
13626         int i;
13627         r_decalsystem_splatqueue_t *queue;
13628
13629         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13630                 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);
13631         r_decalsystem_numqueued = 0;
13632 }
13633
13634 extern cvar_t cl_decals_max;
13635 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13636 {
13637         int i;
13638         decalsystem_t *decalsystem = &ent->decalsystem;
13639         int numdecals;
13640         int killsequence;
13641         tridecal_t *decal;
13642         float frametime;
13643         float lifetime;
13644
13645         if (!decalsystem->numdecals)
13646                 return;
13647
13648         if (r_showsurfaces.integer)
13649                 return;
13650
13651         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13652         {
13653                 R_DecalSystem_Reset(decalsystem);
13654                 return;
13655         }
13656
13657         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13658         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13659
13660         if (decalsystem->lastupdatetime)
13661                 frametime = (cl.time - decalsystem->lastupdatetime);
13662         else
13663                 frametime = 0;
13664         decalsystem->lastupdatetime = cl.time;
13665         decal = decalsystem->decals;
13666         numdecals = decalsystem->numdecals;
13667
13668         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13669         {
13670                 if (decal->color4ub[0][3])
13671                 {
13672                         decal->lived += frametime;
13673                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13674                         {
13675                                 memset(decal, 0, sizeof(*decal));
13676                                 if (decalsystem->freedecal > i)
13677                                         decalsystem->freedecal = i;
13678                         }
13679                 }
13680         }
13681         decal = decalsystem->decals;
13682         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13683                 numdecals--;
13684
13685         // collapse the array by shuffling the tail decals into the gaps
13686         for (;;)
13687         {
13688                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13689                         decalsystem->freedecal++;
13690                 if (decalsystem->freedecal == numdecals)
13691                         break;
13692                 decal[decalsystem->freedecal] = decal[--numdecals];
13693         }
13694
13695         decalsystem->numdecals = numdecals;
13696
13697         if (numdecals <= 0)
13698         {
13699                 // if there are no decals left, reset decalsystem
13700                 R_DecalSystem_Reset(decalsystem);
13701         }
13702 }
13703
13704 extern skinframe_t *decalskinframe;
13705 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13706 {
13707         int i;
13708         decalsystem_t *decalsystem = &ent->decalsystem;
13709         int numdecals;
13710         tridecal_t *decal;
13711         float faderate;
13712         float alpha;
13713         float *v3f;
13714         float *c4f;
13715         float *t2f;
13716         const int *e;
13717         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13718         int numtris = 0;
13719
13720         numdecals = decalsystem->numdecals;
13721         if (!numdecals)
13722                 return;
13723
13724         if (r_showsurfaces.integer)
13725                 return;
13726
13727         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13728         {
13729                 R_DecalSystem_Reset(decalsystem);
13730                 return;
13731         }
13732
13733         // if the model is static it doesn't matter what value we give for
13734         // wantnormals and wanttangents, so this logic uses only rules applicable
13735         // to a model, knowing that they are meaningless otherwise
13736         if (ent == r_refdef.scene.worldentity)
13737                 RSurf_ActiveWorldEntity();
13738         else
13739                 RSurf_ActiveModelEntity(ent, false, false, false);
13740
13741         decalsystem->lastupdatetime = cl.time;
13742         decal = decalsystem->decals;
13743
13744         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13745
13746         // update vertex positions for animated models
13747         v3f = decalsystem->vertex3f;
13748         c4f = decalsystem->color4f;
13749         t2f = decalsystem->texcoord2f;
13750         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13751         {
13752                 if (!decal->color4ub[0][3])
13753                         continue;
13754
13755                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13756                         continue;
13757
13758                 // update color values for fading decals
13759                 if (decal->lived >= cl_decals_time.value)
13760                 {
13761                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13762                         alpha *= (1.0f/255.0f);
13763                 }
13764                 else
13765                         alpha = 1.0f/255.0f;
13766
13767                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13768                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13769                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13770                 c4f[ 3] = 1;
13771                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13772                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13773                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13774                 c4f[ 7] = 1;
13775                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13776                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13777                 c4f[10] = decal->color4ub[2][2] * alpha;
13778                 c4f[11] = 1;
13779
13780                 t2f[0] = decal->texcoord2f[0][0];
13781                 t2f[1] = decal->texcoord2f[0][1];
13782                 t2f[2] = decal->texcoord2f[1][0];
13783                 t2f[3] = decal->texcoord2f[1][1];
13784                 t2f[4] = decal->texcoord2f[2][0];
13785                 t2f[5] = decal->texcoord2f[2][1];
13786
13787                 // update vertex positions for animated models
13788                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13789                 {
13790                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13791                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13792                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13793                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13794                 }
13795                 else
13796                 {
13797                         VectorCopy(decal->vertex3f[0], v3f);
13798                         VectorCopy(decal->vertex3f[1], v3f + 3);
13799                         VectorCopy(decal->vertex3f[2], v3f + 6);
13800                 }
13801
13802                 if (r_refdef.fogenabled)
13803                 {
13804                         alpha = RSurf_FogVertex(v3f);
13805                         VectorScale(c4f, alpha, c4f);
13806                         alpha = RSurf_FogVertex(v3f + 3);
13807                         VectorScale(c4f + 4, alpha, c4f + 4);
13808                         alpha = RSurf_FogVertex(v3f + 6);
13809                         VectorScale(c4f + 8, alpha, c4f + 8);
13810                 }
13811
13812                 v3f += 9;
13813                 c4f += 12;
13814                 t2f += 6;
13815                 numtris++;
13816         }
13817
13818         if (numtris > 0)
13819         {
13820                 r_refdef.stats.drawndecals += numtris;
13821
13822                 // now render the decals all at once
13823                 // (this assumes they all use one particle font texture!)
13824                 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);
13825                 R_Mesh_ResetTextureState();
13826                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13827                 GL_DepthMask(false);
13828                 GL_DepthRange(0, 1);
13829                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13830                 GL_DepthTest(true);
13831                 GL_CullFace(GL_NONE);
13832                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13833                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13834                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13835         }
13836 }
13837
13838 static void R_DrawModelDecals(void)
13839 {
13840         int i, numdecals;
13841
13842         // fade faster when there are too many decals
13843         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13844         for (i = 0;i < r_refdef.scene.numentities;i++)
13845                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13846
13847         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13848         for (i = 0;i < r_refdef.scene.numentities;i++)
13849                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13850                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13851
13852         R_DecalSystem_ApplySplatEntitiesQueue();
13853
13854         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13855         for (i = 0;i < r_refdef.scene.numentities;i++)
13856                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13857
13858         r_refdef.stats.totaldecals += numdecals;
13859
13860         if (r_showsurfaces.integer)
13861                 return;
13862
13863         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13864
13865         for (i = 0;i < r_refdef.scene.numentities;i++)
13866         {
13867                 if (!r_refdef.viewcache.entityvisible[i])
13868                         continue;
13869                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13870                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13871         }
13872 }
13873
13874 extern cvar_t mod_collision_bih;
13875 void R_DrawDebugModel(void)
13876 {
13877         entity_render_t *ent = rsurface.entity;
13878         int i, j, k, l, flagsmask;
13879         const msurface_t *surface;
13880         dp_model_t *model = ent->model;
13881         vec3_t v;
13882
13883         switch(vid.renderpath)
13884         {
13885         case RENDERPATH_GL11:
13886         case RENDERPATH_GL13:
13887         case RENDERPATH_GL20:
13888         case RENDERPATH_CGGL:
13889                 break;
13890         case RENDERPATH_D3D9:
13891                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13892                 return;
13893         case RENDERPATH_D3D10:
13894                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13895                 return;
13896         case RENDERPATH_D3D11:
13897                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13898                 return;
13899         }
13900
13901         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13902
13903         R_Mesh_ResetTextureState();
13904         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13905         GL_DepthRange(0, 1);
13906         GL_DepthTest(!r_showdisabledepthtest.integer);
13907         GL_DepthMask(false);
13908         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13909
13910         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13911         {
13912                 int triangleindex;
13913                 int bihleafindex;
13914                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13915                 const q3mbrush_t *brush;
13916                 const bih_t *bih = &model->collision_bih;
13917                 const bih_leaf_t *bihleaf;
13918                 float vertex3f[3][3];
13919                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13920                 cullbox = false;
13921                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13922                 {
13923                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13924                                 continue;
13925                         switch (bihleaf->type)
13926                         {
13927                         case BIH_BRUSH:
13928                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13929                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13930                                 {
13931                                         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);
13932                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13933                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13934                                 }
13935                                 break;
13936                         case BIH_COLLISIONTRIANGLE:
13937                                 triangleindex = bihleaf->itemindex;
13938                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13939                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13940                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13941                                 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);
13942                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13943                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13944                                 break;
13945                         case BIH_RENDERTRIANGLE:
13946                                 triangleindex = bihleaf->itemindex;
13947                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13948                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13949                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13950                                 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);
13951                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13952                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13953                                 break;
13954                         }
13955                 }
13956         }
13957
13958         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13959
13960         if (r_showtris.integer || r_shownormals.integer)
13961         {
13962                 if (r_showdisabledepthtest.integer)
13963                 {
13964                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13965                         GL_DepthMask(false);
13966                 }
13967                 else
13968                 {
13969                         GL_BlendFunc(GL_ONE, GL_ZERO);
13970                         GL_DepthMask(true);
13971                 }
13972                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13973                 {
13974                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13975                                 continue;
13976                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13977                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13978                         {
13979                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13980                                 if (r_showtris.value > 0)
13981                                 {
13982                                         if (!rsurface.texture->currentlayers->depthmask)
13983                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13984                                         else if (ent == r_refdef.scene.worldentity)
13985                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13986                                         else
13987                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13988                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13989                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13990                                         RSurf_DrawBatch();
13991                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13992                                         CHECKGLERROR
13993                                 }
13994                                 if (r_shownormals.value < 0)
13995                                 {
13996                                         qglBegin(GL_LINES);
13997                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13998                                         {
13999                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14000                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14001                                                 qglVertex3f(v[0], v[1], v[2]);
14002                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14003                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14004                                                 qglVertex3f(v[0], v[1], v[2]);
14005                                         }
14006                                         qglEnd();
14007                                         CHECKGLERROR
14008                                 }
14009                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14010                                 {
14011                                         qglBegin(GL_LINES);
14012                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14013                                         {
14014                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14015                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14016                                                 qglVertex3f(v[0], v[1], v[2]);
14017                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14018                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14019                                                 qglVertex3f(v[0], v[1], v[2]);
14020                                         }
14021                                         qglEnd();
14022                                         CHECKGLERROR
14023                                         qglBegin(GL_LINES);
14024                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14025                                         {
14026                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14027                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14028                                                 qglVertex3f(v[0], v[1], v[2]);
14029                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14030                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14031                                                 qglVertex3f(v[0], v[1], v[2]);
14032                                         }
14033                                         qglEnd();
14034                                         CHECKGLERROR
14035                                         qglBegin(GL_LINES);
14036                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14037                                         {
14038                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14039                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14040                                                 qglVertex3f(v[0], v[1], v[2]);
14041                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14042                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14043                                                 qglVertex3f(v[0], v[1], v[2]);
14044                                         }
14045                                         qglEnd();
14046                                         CHECKGLERROR
14047                                 }
14048                         }
14049                 }
14050                 rsurface.texture = NULL;
14051         }
14052 }
14053
14054 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14055 int r_maxsurfacelist = 0;
14056 const msurface_t **r_surfacelist = NULL;
14057 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14058 {
14059         int i, j, endj, flagsmask;
14060         dp_model_t *model = r_refdef.scene.worldmodel;
14061         msurface_t *surfaces;
14062         unsigned char *update;
14063         int numsurfacelist = 0;
14064         if (model == NULL)
14065                 return;
14066
14067         if (r_maxsurfacelist < model->num_surfaces)
14068         {
14069                 r_maxsurfacelist = model->num_surfaces;
14070                 if (r_surfacelist)
14071                         Mem_Free((msurface_t**)r_surfacelist);
14072                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14073         }
14074
14075         RSurf_ActiveWorldEntity();
14076
14077         surfaces = model->data_surfaces;
14078         update = model->brushq1.lightmapupdateflags;
14079
14080         // update light styles on this submodel
14081         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14082         {
14083                 model_brush_lightstyleinfo_t *style;
14084                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14085                 {
14086                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14087                         {
14088                                 int *list = style->surfacelist;
14089                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14090                                 for (j = 0;j < style->numsurfaces;j++)
14091                                         update[list[j]] = true;
14092                         }
14093                 }
14094         }
14095
14096         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14097
14098         if (debug)
14099         {
14100                 R_DrawDebugModel();
14101                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14102                 return;
14103         }
14104
14105         rsurface.lightmaptexture = NULL;
14106         rsurface.deluxemaptexture = NULL;
14107         rsurface.uselightmaptexture = false;
14108         rsurface.texture = NULL;
14109         rsurface.rtlight = NULL;
14110         numsurfacelist = 0;
14111         // add visible surfaces to draw list
14112         for (i = 0;i < model->nummodelsurfaces;i++)
14113         {
14114                 j = model->sortedmodelsurfaces[i];
14115                 if (r_refdef.viewcache.world_surfacevisible[j])
14116                         r_surfacelist[numsurfacelist++] = surfaces + j;
14117         }
14118         // update lightmaps if needed
14119         if (model->brushq1.firstrender)
14120         {
14121                 model->brushq1.firstrender = false;
14122                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14123                         if (update[j])
14124                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14125         }
14126         else if (update)
14127         {
14128                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14129                         if (r_refdef.viewcache.world_surfacevisible[j])
14130                                 if (update[j])
14131                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14132         }
14133         // don't do anything if there were no surfaces
14134         if (!numsurfacelist)
14135         {
14136                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14137                 return;
14138         }
14139         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14140         GL_AlphaTest(false);
14141
14142         // add to stats if desired
14143         if (r_speeds.integer && !skysurfaces && !depthonly)
14144         {
14145                 r_refdef.stats.world_surfaces += numsurfacelist;
14146                 for (j = 0;j < numsurfacelist;j++)
14147                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14148         }
14149
14150         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14151 }
14152
14153 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14154 {
14155         int i, j, endj, flagsmask;
14156         dp_model_t *model = ent->model;
14157         msurface_t *surfaces;
14158         unsigned char *update;
14159         int numsurfacelist = 0;
14160         if (model == NULL)
14161                 return;
14162
14163         if (r_maxsurfacelist < model->num_surfaces)
14164         {
14165                 r_maxsurfacelist = model->num_surfaces;
14166                 if (r_surfacelist)
14167                         Mem_Free((msurface_t **)r_surfacelist);
14168                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14169         }
14170
14171         // if the model is static it doesn't matter what value we give for
14172         // wantnormals and wanttangents, so this logic uses only rules applicable
14173         // to a model, knowing that they are meaningless otherwise
14174         if (ent == r_refdef.scene.worldentity)
14175                 RSurf_ActiveWorldEntity();
14176         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14177                 RSurf_ActiveModelEntity(ent, false, false, false);
14178         else if (prepass)
14179                 RSurf_ActiveModelEntity(ent, true, true, true);
14180         else if (depthonly)
14181         {
14182                 switch (vid.renderpath)
14183                 {
14184                 case RENDERPATH_GL20:
14185                 case RENDERPATH_CGGL:
14186                 case RENDERPATH_D3D9:
14187                 case RENDERPATH_D3D10:
14188                 case RENDERPATH_D3D11:
14189                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14190                         break;
14191                 case RENDERPATH_GL13:
14192                 case RENDERPATH_GL11:
14193                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14194                         break;
14195                 }
14196         }
14197         else
14198         {
14199                 switch (vid.renderpath)
14200                 {
14201                 case RENDERPATH_GL20:
14202                 case RENDERPATH_CGGL:
14203                 case RENDERPATH_D3D9:
14204                 case RENDERPATH_D3D10:
14205                 case RENDERPATH_D3D11:
14206                         RSurf_ActiveModelEntity(ent, true, true, false);
14207                         break;
14208                 case RENDERPATH_GL13:
14209                 case RENDERPATH_GL11:
14210                         RSurf_ActiveModelEntity(ent, true, false, false);
14211                         break;
14212                 }
14213         }
14214
14215         surfaces = model->data_surfaces;
14216         update = model->brushq1.lightmapupdateflags;
14217
14218         // update light styles
14219         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14220         {
14221                 model_brush_lightstyleinfo_t *style;
14222                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14223                 {
14224                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14225                         {
14226                                 int *list = style->surfacelist;
14227                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14228                                 for (j = 0;j < style->numsurfaces;j++)
14229                                         update[list[j]] = true;
14230                         }
14231                 }
14232         }
14233
14234         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14235
14236         if (debug)
14237         {
14238                 R_DrawDebugModel();
14239                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14240                 return;
14241         }
14242
14243         rsurface.lightmaptexture = NULL;
14244         rsurface.deluxemaptexture = NULL;
14245         rsurface.uselightmaptexture = false;
14246         rsurface.texture = NULL;
14247         rsurface.rtlight = NULL;
14248         numsurfacelist = 0;
14249         // add visible surfaces to draw list
14250         for (i = 0;i < model->nummodelsurfaces;i++)
14251                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14252         // don't do anything if there were no surfaces
14253         if (!numsurfacelist)
14254         {
14255                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14256                 return;
14257         }
14258         // update lightmaps if needed
14259         if (update)
14260         {
14261                 int updated = 0;
14262                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14263                 {
14264                         if (update[j])
14265                         {
14266                                 updated++;
14267                                 R_BuildLightMap(ent, surfaces + j);
14268                         }
14269                 }
14270         }
14271         if (update)
14272                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14273                         if (update[j])
14274                                 R_BuildLightMap(ent, surfaces + j);
14275         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14276         GL_AlphaTest(false);
14277
14278         // add to stats if desired
14279         if (r_speeds.integer && !skysurfaces && !depthonly)
14280         {
14281                 r_refdef.stats.entities_surfaces += numsurfacelist;
14282                 for (j = 0;j < numsurfacelist;j++)
14283                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14284         }
14285
14286         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14287 }
14288
14289 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14290 {
14291         static texture_t texture;
14292         static msurface_t surface;
14293         const msurface_t *surfacelist = &surface;
14294
14295         // fake enough texture and surface state to render this geometry
14296
14297         texture.update_lastrenderframe = -1; // regenerate this texture
14298         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14299         texture.currentskinframe = skinframe;
14300         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14301         texture.offsetmapping = OFFSETMAPPING_OFF;
14302         texture.offsetscale = 1;
14303         texture.specularscalemod = 1;
14304         texture.specularpowermod = 1;
14305
14306         surface.texture = &texture;
14307         surface.num_triangles = numtriangles;
14308         surface.num_firsttriangle = firsttriangle;
14309         surface.num_vertices = numvertices;
14310         surface.num_firstvertex = firstvertex;
14311
14312         // now render it
14313         rsurface.texture = R_GetCurrentTexture(surface.texture);
14314         rsurface.lightmaptexture = NULL;
14315         rsurface.deluxemaptexture = NULL;
14316         rsurface.uselightmaptexture = false;
14317         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14318 }
14319
14320 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)
14321 {
14322         static msurface_t surface;
14323         const msurface_t *surfacelist = &surface;
14324
14325         // fake enough texture and surface state to render this geometry
14326
14327         surface.texture = texture;
14328         surface.num_triangles = numtriangles;
14329         surface.num_firsttriangle = firsttriangle;
14330         surface.num_vertices = numvertices;
14331         surface.num_firstvertex = firstvertex;
14332
14333         // now render it
14334         rsurface.texture = R_GetCurrentTexture(surface.texture);
14335         rsurface.lightmaptexture = NULL;
14336         rsurface.deluxemaptexture = NULL;
14337         rsurface.uselightmaptexture = false;
14338         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14339 }