]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
get rid of calculating vertexmesh animcache buffers if we do not need the vertexmesh...
[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
7765         // identical memory layout, so no need to allocate...
7766         // this also provides the vertexposition structure to everything, e.g.
7767         // depth masked rendering currently uses it even if having separate
7768         // arrays
7769         // NOTE: get rid of this optimization if changing it to e.g. 4f
7770         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7771
7772         // TODO:
7773         // get rid of following uses of VERTEXPOSITION, change to the array:
7774         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7775         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7776         // R_DrawTextureSurfaceList_DepthOnly
7777         // R_Q1BSP_DrawShadowMap
7778
7779         switch(vid.renderpath)
7780         {
7781         case RENDERPATH_GL20:
7782         case RENDERPATH_CGGL:
7783                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7784                 if (gl_mesh_separatearrays.integer)
7785                         return;
7786                 break;
7787         case RENDERPATH_D3D9:
7788         case RENDERPATH_D3D10:
7789         case RENDERPATH_D3D11:
7790                 // always need the meshbuffers
7791                 break;
7792         case RENDERPATH_GL13:
7793         case RENDERPATH_GL11:
7794                 // never need the meshbuffers
7795                 return;
7796         }
7797
7798         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7799                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7800         /*
7801         if (!ent->animcache_vertexposition)
7802                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7803         */
7804         if (ent->animcache_vertexposition)
7805         {
7806                 /*
7807                 for (i = 0;i < numvertices;i++)
7808                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
7809                 */
7810                 // TODO: upload vertex buffer?
7811         }
7812         if (ent->animcache_vertexmesh)
7813         {
7814                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7815                 for (i = 0;i < numvertices;i++)
7816                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
7817                 if (ent->animcache_svector3f)
7818                         for (i = 0;i < numvertices;i++)
7819                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
7820                 if (ent->animcache_tvector3f)
7821                         for (i = 0;i < numvertices;i++)
7822                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
7823                 if (ent->animcache_normal3f)
7824                         for (i = 0;i < numvertices;i++)
7825                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
7826                 // TODO: upload vertex buffer?
7827         }
7828 }
7829
7830 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7831 {
7832         dp_model_t *model = ent->model;
7833         int numvertices;
7834         // see if it's already cached this frame
7835         if (ent->animcache_vertex3f)
7836         {
7837                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7838                 if (wantnormals || wanttangents)
7839                 {
7840                         if (ent->animcache_normal3f)
7841                                 wantnormals = false;
7842                         if (ent->animcache_svector3f)
7843                                 wanttangents = false;
7844                         if (wantnormals || wanttangents)
7845                         {
7846                                 numvertices = model->surfmesh.num_vertices;
7847                                 if (wantnormals)
7848                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7849                                 if (wanttangents)
7850                                 {
7851                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7852                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7853                                 }
7854                                 if (!r_framedata_failed)
7855                                 {
7856                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7857                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7858                                 }
7859                         }
7860                 }
7861         }
7862         else
7863         {
7864                 // see if this ent is worth caching
7865                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7866                         return false;
7867                 // get some memory for this entity and generate mesh data
7868                 numvertices = model->surfmesh.num_vertices;
7869                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7870                 if (wantnormals)
7871                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7872                 if (wanttangents)
7873                 {
7874                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7875                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7876                 }
7877                 if (!r_framedata_failed)
7878                 {
7879                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7880                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7881                 }
7882         }
7883         return !r_framedata_failed;
7884 }
7885
7886 void R_AnimCache_CacheVisibleEntities(void)
7887 {
7888         int i;
7889         qboolean wantnormals = true;
7890         qboolean wanttangents = !r_showsurfaces.integer;
7891
7892         switch(vid.renderpath)
7893         {
7894         case RENDERPATH_GL20:
7895         case RENDERPATH_CGGL:
7896         case RENDERPATH_D3D9:
7897         case RENDERPATH_D3D10:
7898         case RENDERPATH_D3D11:
7899                 break;
7900         case RENDERPATH_GL13:
7901         case RENDERPATH_GL11:
7902                 wanttangents = false;
7903                 break;
7904         }
7905
7906         if (r_shownormals.integer)
7907                 wanttangents = wantnormals = true;
7908
7909         // TODO: thread this
7910         // NOTE: R_PrepareRTLights() also caches entities
7911
7912         for (i = 0;i < r_refdef.scene.numentities;i++)
7913                 if (r_refdef.viewcache.entityvisible[i])
7914                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7915 }
7916
7917 //==================================================================================
7918
7919 static void R_View_UpdateEntityLighting (void)
7920 {
7921         int i;
7922         entity_render_t *ent;
7923         vec3_t tempdiffusenormal, avg;
7924         vec_t f, fa, fd, fdd;
7925         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7926
7927         for (i = 0;i < r_refdef.scene.numentities;i++)
7928         {
7929                 ent = r_refdef.scene.entities[i];
7930
7931                 // skip unseen models
7932                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7933                         continue;
7934
7935                 // skip bsp models
7936                 if (ent->model && ent->model->brush.num_leafs)
7937                 {
7938                         // TODO: use modellight for r_ambient settings on world?
7939                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7940                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7941                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7942                         continue;
7943                 }
7944
7945                 // fetch the lighting from the worldmodel data
7946                 VectorClear(ent->modellight_ambient);
7947                 VectorClear(ent->modellight_diffuse);
7948                 VectorClear(tempdiffusenormal);
7949                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7950                 {
7951                         vec3_t org;
7952                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7953                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7954                         if(ent->flags & RENDER_EQUALIZE)
7955                         {
7956                                 // first fix up ambient lighting...
7957                                 if(r_equalize_entities_minambient.value > 0)
7958                                 {
7959                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7960                                         if(fd > 0)
7961                                         {
7962                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7963                                                 if(fa < r_equalize_entities_minambient.value * fd)
7964                                                 {
7965                                                         // solve:
7966                                                         //   fa'/fd' = minambient
7967                                                         //   fa'+0.25*fd' = fa+0.25*fd
7968                                                         //   ...
7969                                                         //   fa' = fd' * minambient
7970                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7971                                                         //   ...
7972                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7973                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7974                                                         //   ...
7975                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7976                                                         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
7977                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7978                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7979                                                 }
7980                                         }
7981                                 }
7982
7983                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7984                                 {
7985                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7986                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7987                                         if(f > 0)
7988                                         {
7989                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7990                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7991                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7992                                         }
7993                                 }
7994                         }
7995                 }
7996                 else // highly rare
7997                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7998
7999                 // move the light direction into modelspace coordinates for lighting code
8000                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8001                 if(VectorLength2(ent->modellight_lightdir) == 0)
8002                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8003                 VectorNormalize(ent->modellight_lightdir);
8004         }
8005 }
8006
8007 #define MAX_LINEOFSIGHTTRACES 64
8008
8009 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8010 {
8011         int i;
8012         vec3_t boxmins, boxmaxs;
8013         vec3_t start;
8014         vec3_t end;
8015         dp_model_t *model = r_refdef.scene.worldmodel;
8016
8017         if (!model || !model->brush.TraceLineOfSight)
8018                 return true;
8019
8020         // expand the box a little
8021         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8022         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8023         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8024         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8025         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8026         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8027
8028         // return true if eye is inside enlarged box
8029         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8030                 return true;
8031
8032         // try center
8033         VectorCopy(eye, start);
8034         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8035         if (model->brush.TraceLineOfSight(model, start, end))
8036                 return true;
8037
8038         // try various random positions
8039         for (i = 0;i < numsamples;i++)
8040         {
8041                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8042                 if (model->brush.TraceLineOfSight(model, start, end))
8043                         return true;
8044         }
8045
8046         return false;
8047 }
8048
8049
8050 static void R_View_UpdateEntityVisible (void)
8051 {
8052         int i;
8053         int renderimask;
8054         int samples;
8055         entity_render_t *ent;
8056
8057         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8058                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8059                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8060                 :                                                          RENDER_EXTERIORMODEL;
8061         if (!r_drawviewmodel.integer)
8062                 renderimask |= RENDER_VIEWMODEL;
8063         if (!r_drawexteriormodel.integer)
8064                 renderimask |= RENDER_EXTERIORMODEL;
8065         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8066         {
8067                 // worldmodel can check visibility
8068                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8069                 for (i = 0;i < r_refdef.scene.numentities;i++)
8070                 {
8071                         ent = r_refdef.scene.entities[i];
8072                         if (!(ent->flags & renderimask))
8073                         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)))
8074                         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))
8075                                 r_refdef.viewcache.entityvisible[i] = true;
8076                 }
8077                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8078                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8079                 {
8080                         for (i = 0;i < r_refdef.scene.numentities;i++)
8081                         {
8082                                 ent = r_refdef.scene.entities[i];
8083                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8084                                 {
8085                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8086                                         if (samples < 0)
8087                                                 continue; // temp entities do pvs only
8088                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8089                                                 ent->last_trace_visibility = realtime;
8090                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8091                                                 r_refdef.viewcache.entityvisible[i] = 0;
8092                                 }
8093                         }
8094                 }
8095         }
8096         else
8097         {
8098                 // no worldmodel or it can't check visibility
8099                 for (i = 0;i < r_refdef.scene.numentities;i++)
8100                 {
8101                         ent = r_refdef.scene.entities[i];
8102                         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));
8103                 }
8104         }
8105 }
8106
8107 /// only used if skyrendermasked, and normally returns false
8108 int R_DrawBrushModelsSky (void)
8109 {
8110         int i, sky;
8111         entity_render_t *ent;
8112
8113         sky = false;
8114         for (i = 0;i < r_refdef.scene.numentities;i++)
8115         {
8116                 if (!r_refdef.viewcache.entityvisible[i])
8117                         continue;
8118                 ent = r_refdef.scene.entities[i];
8119                 if (!ent->model || !ent->model->DrawSky)
8120                         continue;
8121                 ent->model->DrawSky(ent);
8122                 sky = true;
8123         }
8124         return sky;
8125 }
8126
8127 static void R_DrawNoModel(entity_render_t *ent);
8128 static void R_DrawModels(void)
8129 {
8130         int i;
8131         entity_render_t *ent;
8132
8133         for (i = 0;i < r_refdef.scene.numentities;i++)
8134         {
8135                 if (!r_refdef.viewcache.entityvisible[i])
8136                         continue;
8137                 ent = r_refdef.scene.entities[i];
8138                 r_refdef.stats.entities++;
8139                 if (ent->model && ent->model->Draw != NULL)
8140                         ent->model->Draw(ent);
8141                 else
8142                         R_DrawNoModel(ent);
8143         }
8144 }
8145
8146 static void R_DrawModelsDepth(void)
8147 {
8148         int i;
8149         entity_render_t *ent;
8150
8151         for (i = 0;i < r_refdef.scene.numentities;i++)
8152         {
8153                 if (!r_refdef.viewcache.entityvisible[i])
8154                         continue;
8155                 ent = r_refdef.scene.entities[i];
8156                 if (ent->model && ent->model->DrawDepth != NULL)
8157                         ent->model->DrawDepth(ent);
8158         }
8159 }
8160
8161 static void R_DrawModelsDebug(void)
8162 {
8163         int i;
8164         entity_render_t *ent;
8165
8166         for (i = 0;i < r_refdef.scene.numentities;i++)
8167         {
8168                 if (!r_refdef.viewcache.entityvisible[i])
8169                         continue;
8170                 ent = r_refdef.scene.entities[i];
8171                 if (ent->model && ent->model->DrawDebug != NULL)
8172                         ent->model->DrawDebug(ent);
8173         }
8174 }
8175
8176 static void R_DrawModelsAddWaterPlanes(void)
8177 {
8178         int i;
8179         entity_render_t *ent;
8180
8181         for (i = 0;i < r_refdef.scene.numentities;i++)
8182         {
8183                 if (!r_refdef.viewcache.entityvisible[i])
8184                         continue;
8185                 ent = r_refdef.scene.entities[i];
8186                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8187                         ent->model->DrawAddWaterPlanes(ent);
8188         }
8189 }
8190
8191 static void R_View_SetFrustum(void)
8192 {
8193         int i;
8194         double slopex, slopey;
8195         vec3_t forward, left, up, origin;
8196
8197         // we can't trust r_refdef.view.forward and friends in reflected scenes
8198         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8199
8200 #if 0
8201         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8202         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8203         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8204         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8205         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8206         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8207         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8208         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8209         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8210         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8211         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8212         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8213 #endif
8214
8215 #if 0
8216         zNear = r_refdef.nearclip;
8217         nudge = 1.0 - 1.0 / (1<<23);
8218         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8219         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8220         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8221         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8222         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8223         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8224         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8225         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8226 #endif
8227
8228
8229
8230 #if 0
8231         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8232         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8233         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8234         r_refdef.view.frustum[0].dist = m[15] - m[12];
8235
8236         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8237         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8238         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8239         r_refdef.view.frustum[1].dist = m[15] + m[12];
8240
8241         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8242         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8243         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8244         r_refdef.view.frustum[2].dist = m[15] - m[13];
8245
8246         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8247         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8248         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8249         r_refdef.view.frustum[3].dist = m[15] + m[13];
8250
8251         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8252         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8253         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8254         r_refdef.view.frustum[4].dist = m[15] - m[14];
8255
8256         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8257         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8258         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8259         r_refdef.view.frustum[5].dist = m[15] + m[14];
8260 #endif
8261
8262         if (r_refdef.view.useperspective)
8263         {
8264                 slopex = 1.0 / r_refdef.view.frustum_x;
8265                 slopey = 1.0 / r_refdef.view.frustum_y;
8266                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8267                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8268                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8269                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8270                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8271
8272                 // Leaving those out was a mistake, those were in the old code, and they
8273                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8274                 // I couldn't reproduce it after adding those normalizations. --blub
8275                 VectorNormalize(r_refdef.view.frustum[0].normal);
8276                 VectorNormalize(r_refdef.view.frustum[1].normal);
8277                 VectorNormalize(r_refdef.view.frustum[2].normal);
8278                 VectorNormalize(r_refdef.view.frustum[3].normal);
8279
8280                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8281                 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]);
8282                 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]);
8283                 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]);
8284                 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]);
8285
8286                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8287                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8288                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8289                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8290                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8291         }
8292         else
8293         {
8294                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8295                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8296                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8297                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8298                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8299                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8300                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8301                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8302                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8303                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8304         }
8305         r_refdef.view.numfrustumplanes = 5;
8306
8307         if (r_refdef.view.useclipplane)
8308         {
8309                 r_refdef.view.numfrustumplanes = 6;
8310                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8311         }
8312
8313         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8314                 PlaneClassify(r_refdef.view.frustum + i);
8315
8316         // LordHavoc: note to all quake engine coders, Quake had a special case
8317         // for 90 degrees which assumed a square view (wrong), so I removed it,
8318         // Quake2 has it disabled as well.
8319
8320         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8321         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8322         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8323         //PlaneClassify(&frustum[0]);
8324
8325         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8326         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8327         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8328         //PlaneClassify(&frustum[1]);
8329
8330         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8331         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8332         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8333         //PlaneClassify(&frustum[2]);
8334
8335         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8336         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8337         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8338         //PlaneClassify(&frustum[3]);
8339
8340         // nearclip plane
8341         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8342         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8343         //PlaneClassify(&frustum[4]);
8344 }
8345
8346 void R_View_Update(void)
8347 {
8348         R_Main_ResizeViewCache();
8349         R_View_SetFrustum();
8350         R_View_WorldVisibility(r_refdef.view.useclipplane);
8351         R_View_UpdateEntityVisible();
8352         R_View_UpdateEntityLighting();
8353 }
8354
8355 void R_SetupView(qboolean allowwaterclippingplane)
8356 {
8357         const float *customclipplane = NULL;
8358         float plane[4];
8359         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8360         {
8361                 // LordHavoc: couldn't figure out how to make this approach the
8362                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8363                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8364                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8365                         dist = r_refdef.view.clipplane.dist;
8366                 plane[0] = r_refdef.view.clipplane.normal[0];
8367                 plane[1] = r_refdef.view.clipplane.normal[1];
8368                 plane[2] = r_refdef.view.clipplane.normal[2];
8369                 plane[3] = dist;
8370                 customclipplane = plane;
8371         }
8372
8373         if (!r_refdef.view.useperspective)
8374                 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);
8375         else if (vid.stencil && r_useinfinitefarclip.integer)
8376                 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);
8377         else
8378                 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);
8379         R_SetViewport(&r_refdef.view.viewport);
8380 }
8381
8382 void R_EntityMatrix(const matrix4x4_t *matrix)
8383 {
8384         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8385         {
8386                 gl_modelmatrixchanged = false;
8387                 gl_modelmatrix = *matrix;
8388                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8389                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8390                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8391                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8392                 CHECKGLERROR
8393                 switch(vid.renderpath)
8394                 {
8395                 case RENDERPATH_D3D9:
8396 #ifdef SUPPORTD3D
8397                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8398                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8399 #endif
8400                         break;
8401                 case RENDERPATH_D3D10:
8402                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8403                         break;
8404                 case RENDERPATH_D3D11:
8405                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8406                         break;
8407                 case RENDERPATH_GL20:
8408                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8409                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8410                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8411                         break;
8412                 case RENDERPATH_CGGL:
8413 #ifdef SUPPORTCG
8414                         CHECKCGERROR
8415                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8416                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8417                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8418 #endif
8419                         break;
8420                 case RENDERPATH_GL13:
8421                 case RENDERPATH_GL11:
8422                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8423                         break;
8424                 }
8425         }
8426 }
8427
8428 void R_ResetViewRendering2D(void)
8429 {
8430         r_viewport_t viewport;
8431         DrawQ_Finish();
8432
8433         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8434         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);
8435         R_SetViewport(&viewport);
8436         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8437         GL_Color(1, 1, 1, 1);
8438         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8439         GL_BlendFunc(GL_ONE, GL_ZERO);
8440         GL_AlphaTest(false);
8441         GL_ScissorTest(false);
8442         GL_DepthMask(false);
8443         GL_DepthRange(0, 1);
8444         GL_DepthTest(false);
8445         GL_DepthFunc(GL_LEQUAL);
8446         R_EntityMatrix(&identitymatrix);
8447         R_Mesh_ResetTextureState();
8448         GL_PolygonOffset(0, 0);
8449         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8450         switch(vid.renderpath)
8451         {
8452         case RENDERPATH_GL11:
8453         case RENDERPATH_GL13:
8454         case RENDERPATH_GL20:
8455         case RENDERPATH_CGGL:
8456                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8457                 break;
8458         case RENDERPATH_D3D9:
8459         case RENDERPATH_D3D10:
8460         case RENDERPATH_D3D11:
8461                 break;
8462         }
8463         GL_CullFace(GL_NONE);
8464 }
8465
8466 void R_ResetViewRendering3D(void)
8467 {
8468         DrawQ_Finish();
8469
8470         R_SetupView(true);
8471         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8472         GL_Color(1, 1, 1, 1);
8473         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8474         GL_BlendFunc(GL_ONE, GL_ZERO);
8475         GL_AlphaTest(false);
8476         GL_ScissorTest(true);
8477         GL_DepthMask(true);
8478         GL_DepthRange(0, 1);
8479         GL_DepthTest(true);
8480         GL_DepthFunc(GL_LEQUAL);
8481         R_EntityMatrix(&identitymatrix);
8482         R_Mesh_ResetTextureState();
8483         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8484         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8485         switch(vid.renderpath)
8486         {
8487         case RENDERPATH_GL11:
8488         case RENDERPATH_GL13:
8489         case RENDERPATH_GL20:
8490         case RENDERPATH_CGGL:
8491                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8492                 break;
8493         case RENDERPATH_D3D9:
8494         case RENDERPATH_D3D10:
8495         case RENDERPATH_D3D11:
8496                 break;
8497         }
8498         GL_CullFace(r_refdef.view.cullface_back);
8499 }
8500
8501 /*
8502 ================
8503 R_RenderView_UpdateViewVectors
8504 ================
8505 */
8506 static void R_RenderView_UpdateViewVectors(void)
8507 {
8508         // break apart the view matrix into vectors for various purposes
8509         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8510         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8511         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8512         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8513         // make an inverted copy of the view matrix for tracking sprites
8514         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8515 }
8516
8517 void R_RenderScene(void);
8518 void R_RenderWaterPlanes(void);
8519
8520 static void R_Water_StartFrame(void)
8521 {
8522         int i;
8523         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8524         r_waterstate_waterplane_t *p;
8525
8526         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8527                 return;
8528
8529         switch(vid.renderpath)
8530         {
8531         case RENDERPATH_GL20:
8532         case RENDERPATH_CGGL:
8533         case RENDERPATH_D3D9:
8534         case RENDERPATH_D3D10:
8535         case RENDERPATH_D3D11:
8536                 break;
8537         case RENDERPATH_GL13:
8538         case RENDERPATH_GL11:
8539                 return;
8540         }
8541
8542         // set waterwidth and waterheight to the water resolution that will be
8543         // used (often less than the screen resolution for faster rendering)
8544         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8545         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8546
8547         // calculate desired texture sizes
8548         // can't use water if the card does not support the texture size
8549         if (!r_water.integer || r_showsurfaces.integer)
8550                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8551         else if (vid.support.arb_texture_non_power_of_two)
8552         {
8553                 texturewidth = waterwidth;
8554                 textureheight = waterheight;
8555                 camerawidth = waterwidth;
8556                 cameraheight = waterheight;
8557         }
8558         else
8559         {
8560                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8561                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8562                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8563                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8564         }
8565
8566         // allocate textures as needed
8567         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8568         {
8569                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8570                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8571                 {
8572                         if (p->texture_refraction)
8573                                 R_FreeTexture(p->texture_refraction);
8574                         p->texture_refraction = NULL;
8575                         if (p->texture_reflection)
8576                                 R_FreeTexture(p->texture_reflection);
8577                         p->texture_reflection = NULL;
8578                         if (p->texture_camera)
8579                                 R_FreeTexture(p->texture_camera);
8580                         p->texture_camera = NULL;
8581                 }
8582                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8583                 r_waterstate.texturewidth = texturewidth;
8584                 r_waterstate.textureheight = textureheight;
8585                 r_waterstate.camerawidth = camerawidth;
8586                 r_waterstate.cameraheight = cameraheight;
8587         }
8588
8589         if (r_waterstate.texturewidth)
8590         {
8591                 r_waterstate.enabled = true;
8592
8593                 // when doing a reduced render (HDR) we want to use a smaller area
8594                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8595                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8596
8597                 // set up variables that will be used in shader setup
8598                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8599                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8600                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8601                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8602         }
8603
8604         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8605         r_waterstate.numwaterplanes = 0;
8606 }
8607
8608 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8609 {
8610         int triangleindex, planeindex;
8611         const int *e;
8612         vec3_t vert[3];
8613         vec3_t normal;
8614         vec3_t center;
8615         mplane_t plane;
8616         int cam_ent;
8617         r_waterstate_waterplane_t *p;
8618         texture_t *t = R_GetCurrentTexture(surface->texture);
8619         cam_ent = t->camera_entity;
8620         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8621                 cam_ent = 0;
8622
8623         // just use the first triangle with a valid normal for any decisions
8624         VectorClear(normal);
8625         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8626         {
8627                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8628                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8629                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8630                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8631                 if (VectorLength2(normal) >= 0.001)
8632                         break;
8633         }
8634
8635         VectorCopy(normal, plane.normal);
8636         VectorNormalize(plane.normal);
8637         plane.dist = DotProduct(vert[0], plane.normal);
8638         PlaneClassify(&plane);
8639         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8640         {
8641                 // skip backfaces (except if nocullface is set)
8642                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8643                         return;
8644                 VectorNegate(plane.normal, plane.normal);
8645                 plane.dist *= -1;
8646                 PlaneClassify(&plane);
8647         }
8648
8649
8650         // find a matching plane if there is one
8651         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8652                 if(p->camera_entity == t->camera_entity)
8653                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8654                                 break;
8655         if (planeindex >= r_waterstate.maxwaterplanes)
8656                 return; // nothing we can do, out of planes
8657
8658         // if this triangle does not fit any known plane rendered this frame, add one
8659         if (planeindex >= r_waterstate.numwaterplanes)
8660         {
8661                 // store the new plane
8662                 r_waterstate.numwaterplanes++;
8663                 p->plane = plane;
8664                 // clear materialflags and pvs
8665                 p->materialflags = 0;
8666                 p->pvsvalid = false;
8667                 p->camera_entity = t->camera_entity;
8668         }
8669         // merge this surface's materialflags into the waterplane
8670         p->materialflags |= t->currentmaterialflags;
8671         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8672         {
8673                 // merge this surface's PVS into the waterplane
8674                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8675                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8676                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8677                 {
8678                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8679                         p->pvsvalid = true;
8680                 }
8681         }
8682 }
8683
8684 static void R_Water_ProcessPlanes(void)
8685 {
8686         r_refdef_view_t originalview;
8687         r_refdef_view_t myview;
8688         int planeindex;
8689         r_waterstate_waterplane_t *p;
8690         vec3_t visorigin;
8691
8692         originalview = r_refdef.view;
8693
8694         // make sure enough textures are allocated
8695         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8696         {
8697                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8698                 {
8699                         if (!p->texture_refraction)
8700                                 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);
8701                         if (!p->texture_refraction)
8702                                 goto error;
8703                 }
8704                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8705                 {
8706                         if (!p->texture_camera)
8707                                 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);
8708                         if (!p->texture_camera)
8709                                 goto error;
8710                 }
8711
8712                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8713                 {
8714                         if (!p->texture_reflection)
8715                                 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);
8716                         if (!p->texture_reflection)
8717                                 goto error;
8718                 }
8719         }
8720
8721         // render views
8722         r_refdef.view = originalview;
8723         r_refdef.view.showdebug = false;
8724         r_refdef.view.width = r_waterstate.waterwidth;
8725         r_refdef.view.height = r_waterstate.waterheight;
8726         r_refdef.view.useclipplane = true;
8727         myview = r_refdef.view;
8728         r_waterstate.renderingscene = true;
8729         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8730         {
8731                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8732                 {
8733                         r_refdef.view = myview;
8734                         // render reflected scene and copy into texture
8735                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8736                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8737                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8738                         r_refdef.view.clipplane = p->plane;
8739                         // reverse the cullface settings for this render
8740                         r_refdef.view.cullface_front = GL_FRONT;
8741                         r_refdef.view.cullface_back = GL_BACK;
8742                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8743                         {
8744                                 r_refdef.view.usecustompvs = true;
8745                                 if (p->pvsvalid)
8746                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8747                                 else
8748                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8749                         }
8750
8751                         R_ResetViewRendering3D();
8752                         R_ClearScreen(r_refdef.fogenabled);
8753                         R_View_Update();
8754                         R_RenderScene();
8755
8756                         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);
8757                 }
8758
8759                 // render the normal view scene and copy into texture
8760                 // (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)
8761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8762                 {
8763                         r_waterstate.renderingrefraction = true;
8764                         r_refdef.view = myview;
8765
8766                         r_refdef.view.clipplane = p->plane;
8767                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8768                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8769
8770                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8771                         {
8772                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8773                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8774                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8775                                 R_RenderView_UpdateViewVectors();
8776                                 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);
8777                         }
8778
8779                         PlaneClassify(&r_refdef.view.clipplane);
8780
8781                         R_ResetViewRendering3D();
8782                         R_ClearScreen(r_refdef.fogenabled);
8783                         R_View_Update();
8784                         R_RenderScene();
8785
8786                         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);
8787                         r_waterstate.renderingrefraction = false;
8788                 }
8789                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8790                 {
8791                         r_refdef.view = myview;
8792
8793                         r_refdef.view.clipplane = p->plane;
8794                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8795                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8796
8797                         r_refdef.view.width = r_waterstate.camerawidth;
8798                         r_refdef.view.height = r_waterstate.cameraheight;
8799                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8800                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8801
8802                         if(p->camera_entity)
8803                         {
8804                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8805                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8806                         }
8807
8808                         // reverse the cullface settings for this render
8809                         r_refdef.view.cullface_front = GL_FRONT;
8810                         r_refdef.view.cullface_back = GL_BACK;
8811                         // also reverse the view matrix
8812                         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
8813                         R_RenderView_UpdateViewVectors();
8814                         if(p->camera_entity)
8815                                 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);
8816                         
8817                         // camera needs no clipplane
8818                         r_refdef.view.useclipplane = false;
8819
8820                         PlaneClassify(&r_refdef.view.clipplane);
8821
8822                         R_ResetViewRendering3D();
8823                         R_ClearScreen(r_refdef.fogenabled);
8824                         R_View_Update();
8825                         R_RenderScene();
8826
8827                         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);
8828                         r_waterstate.renderingrefraction = false;
8829                 }
8830
8831         }
8832         r_waterstate.renderingscene = false;
8833         r_refdef.view = originalview;
8834         R_ResetViewRendering3D();
8835         R_ClearScreen(r_refdef.fogenabled);
8836         R_View_Update();
8837         return;
8838 error:
8839         r_refdef.view = originalview;
8840         r_waterstate.renderingscene = false;
8841         Cvar_SetValueQuick(&r_water, 0);
8842         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8843         return;
8844 }
8845
8846 void R_Bloom_StartFrame(void)
8847 {
8848         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8849
8850         switch(vid.renderpath)
8851         {
8852         case RENDERPATH_GL20:
8853         case RENDERPATH_CGGL:
8854         case RENDERPATH_D3D9:
8855         case RENDERPATH_D3D10:
8856         case RENDERPATH_D3D11:
8857                 break;
8858         case RENDERPATH_GL13:
8859         case RENDERPATH_GL11:
8860                 return;
8861         }
8862
8863         // set bloomwidth and bloomheight to the bloom resolution that will be
8864         // used (often less than the screen resolution for faster rendering)
8865         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8866         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8867         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8868         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8869         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8870
8871         // calculate desired texture sizes
8872         if (vid.support.arb_texture_non_power_of_two)
8873         {
8874                 screentexturewidth = r_refdef.view.width;
8875                 screentextureheight = r_refdef.view.height;
8876                 bloomtexturewidth = r_bloomstate.bloomwidth;
8877                 bloomtextureheight = r_bloomstate.bloomheight;
8878         }
8879         else
8880         {
8881                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8882                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8883                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8884                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8885         }
8886
8887         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))
8888         {
8889                 Cvar_SetValueQuick(&r_hdr, 0);
8890                 Cvar_SetValueQuick(&r_bloom, 0);
8891                 Cvar_SetValueQuick(&r_motionblur, 0);
8892                 Cvar_SetValueQuick(&r_damageblur, 0);
8893         }
8894
8895         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)))
8896                 screentexturewidth = screentextureheight = 0;
8897         if (!r_hdr.integer && !r_bloom.integer)
8898                 bloomtexturewidth = bloomtextureheight = 0;
8899
8900         // allocate textures as needed
8901         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8902         {
8903                 if (r_bloomstate.texture_screen)
8904                         R_FreeTexture(r_bloomstate.texture_screen);
8905                 r_bloomstate.texture_screen = NULL;
8906                 r_bloomstate.screentexturewidth = screentexturewidth;
8907                 r_bloomstate.screentextureheight = screentextureheight;
8908                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8909                         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);
8910         }
8911         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8912         {
8913                 if (r_bloomstate.texture_bloom)
8914                         R_FreeTexture(r_bloomstate.texture_bloom);
8915                 r_bloomstate.texture_bloom = NULL;
8916                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8917                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8918                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8919                         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);
8920         }
8921
8922         // when doing a reduced render (HDR) we want to use a smaller area
8923         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8924         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8925         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8926         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8927         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8928
8929         // set up a texcoord array for the full resolution screen image
8930         // (we have to keep this around to copy back during final render)
8931         r_bloomstate.screentexcoord2f[0] = 0;
8932         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8933         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8934         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8935         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8936         r_bloomstate.screentexcoord2f[5] = 0;
8937         r_bloomstate.screentexcoord2f[6] = 0;
8938         r_bloomstate.screentexcoord2f[7] = 0;
8939
8940         // set up a texcoord array for the reduced resolution bloom image
8941         // (which will be additive blended over the screen image)
8942         r_bloomstate.bloomtexcoord2f[0] = 0;
8943         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8944         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8945         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8946         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8947         r_bloomstate.bloomtexcoord2f[5] = 0;
8948         r_bloomstate.bloomtexcoord2f[6] = 0;
8949         r_bloomstate.bloomtexcoord2f[7] = 0;
8950
8951         switch(vid.renderpath)
8952         {
8953         case RENDERPATH_GL11:
8954         case RENDERPATH_GL13:
8955         case RENDERPATH_GL20:
8956         case RENDERPATH_CGGL:
8957                 break;
8958         case RENDERPATH_D3D9:
8959         case RENDERPATH_D3D10:
8960         case RENDERPATH_D3D11:
8961                 {
8962                         int i;
8963                         for (i = 0;i < 4;i++)
8964                         {
8965                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8966                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8967                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8968                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8969                         }
8970                 }
8971                 break;
8972         }
8973
8974         if (r_hdr.integer || r_bloom.integer)
8975         {
8976                 r_bloomstate.enabled = true;
8977                 r_bloomstate.hdr = r_hdr.integer != 0;
8978         }
8979
8980         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);
8981 }
8982
8983 void R_Bloom_CopyBloomTexture(float colorscale)
8984 {
8985         r_refdef.stats.bloom++;
8986
8987         // scale down screen texture to the bloom texture size
8988         CHECKGLERROR
8989         R_SetViewport(&r_bloomstate.viewport);
8990         GL_BlendFunc(GL_ONE, GL_ZERO);
8991         GL_Color(colorscale, colorscale, colorscale, 1);
8992         // 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...
8993         switch(vid.renderpath)
8994         {
8995         case RENDERPATH_GL11:
8996         case RENDERPATH_GL13:
8997         case RENDERPATH_GL20:
8998         case RENDERPATH_CGGL:
8999                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9000                 break;
9001         case RENDERPATH_D3D9:
9002         case RENDERPATH_D3D10:
9003         case RENDERPATH_D3D11:
9004                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9005                 break;
9006         }
9007         // TODO: do boxfilter scale-down in shader?
9008         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9009         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9010         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9011
9012         // we now have a bloom image in the framebuffer
9013         // copy it into the bloom image texture for later processing
9014         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);
9015         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9016 }
9017
9018 void R_Bloom_CopyHDRTexture(void)
9019 {
9020         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);
9021         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9022 }
9023
9024 void R_Bloom_MakeTexture(void)
9025 {
9026         int x, range, dir;
9027         float xoffset, yoffset, r, brighten;
9028
9029         r_refdef.stats.bloom++;
9030
9031         R_ResetViewRendering2D();
9032
9033         // we have a bloom image in the framebuffer
9034         CHECKGLERROR
9035         R_SetViewport(&r_bloomstate.viewport);
9036
9037         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9038         {
9039                 x *= 2;
9040                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9041                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9042                 GL_Color(r,r,r,1);
9043                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9044                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9045                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9046                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9047
9048                 // copy the vertically blurred bloom view to a texture
9049                 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);
9050                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9051         }
9052
9053         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9054         brighten = r_bloom_brighten.value;
9055         if (r_hdr.integer)
9056                 brighten *= r_hdr_range.value;
9057         brighten = sqrt(brighten);
9058         if(range >= 1)
9059                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9060         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9061
9062         for (dir = 0;dir < 2;dir++)
9063         {
9064                 // blend on at multiple vertical offsets to achieve a vertical blur
9065                 // TODO: do offset blends using GLSL
9066                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9067                 GL_BlendFunc(GL_ONE, GL_ZERO);
9068                 for (x = -range;x <= range;x++)
9069                 {
9070                         if (!dir){xoffset = 0;yoffset = x;}
9071                         else {xoffset = x;yoffset = 0;}
9072                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9073                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9074                         // compute a texcoord array with the specified x and y offset
9075                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9076                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9077                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9078                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9079                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9080                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9081                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9082                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9083                         // this r value looks like a 'dot' particle, fading sharply to
9084                         // black at the edges
9085                         // (probably not realistic but looks good enough)
9086                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9087                         //r = brighten/(range*2+1);
9088                         r = brighten / (range * 2 + 1);
9089                         if(range >= 1)
9090                                 r *= (1 - x*x/(float)(range*range));
9091                         GL_Color(r, r, r, 1);
9092                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9093                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9094                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9095                         GL_BlendFunc(GL_ONE, GL_ONE);
9096                 }
9097
9098                 // copy the vertically blurred bloom view to a texture
9099                 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);
9100                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9101         }
9102 }
9103
9104 void R_HDR_RenderBloomTexture(void)
9105 {
9106         int oldwidth, oldheight;
9107         float oldcolorscale;
9108
9109         oldcolorscale = r_refdef.view.colorscale;
9110         oldwidth = r_refdef.view.width;
9111         oldheight = r_refdef.view.height;
9112         r_refdef.view.width = r_bloomstate.bloomwidth;
9113         r_refdef.view.height = r_bloomstate.bloomheight;
9114
9115         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9116         // TODO: add exposure compensation features
9117         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9118
9119         r_refdef.view.showdebug = false;
9120         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9121
9122         R_ResetViewRendering3D();
9123
9124         R_ClearScreen(r_refdef.fogenabled);
9125         if (r_timereport_active)
9126                 R_TimeReport("HDRclear");
9127
9128         R_View_Update();
9129         if (r_timereport_active)
9130                 R_TimeReport("visibility");
9131
9132         // only do secondary renders with HDR if r_hdr is 2 or higher
9133         r_waterstate.numwaterplanes = 0;
9134         if (r_waterstate.enabled && r_hdr.integer >= 2)
9135                 R_RenderWaterPlanes();
9136
9137         r_refdef.view.showdebug = true;
9138         R_RenderScene();
9139         r_waterstate.numwaterplanes = 0;
9140
9141         R_ResetViewRendering2D();
9142
9143         R_Bloom_CopyHDRTexture();
9144         R_Bloom_MakeTexture();
9145
9146         // restore the view settings
9147         r_refdef.view.width = oldwidth;
9148         r_refdef.view.height = oldheight;
9149         r_refdef.view.colorscale = oldcolorscale;
9150
9151         R_ResetViewRendering3D();
9152
9153         R_ClearScreen(r_refdef.fogenabled);
9154         if (r_timereport_active)
9155                 R_TimeReport("viewclear");
9156 }
9157
9158 static void R_BlendView(void)
9159 {
9160         unsigned int permutation;
9161         float uservecs[4][4];
9162
9163         switch (vid.renderpath)
9164         {
9165         case RENDERPATH_GL20:
9166         case RENDERPATH_CGGL:
9167         case RENDERPATH_D3D9:
9168         case RENDERPATH_D3D10:
9169         case RENDERPATH_D3D11:
9170                 permutation =
9171                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9172                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9173                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9174                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9175                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9176
9177                 if (r_bloomstate.texture_screen)
9178                 {
9179                         // make sure the buffer is available
9180                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9181
9182                         R_ResetViewRendering2D();
9183
9184                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9185                         {
9186                                 // declare variables
9187                                 float speed;
9188                                 static float avgspeed;
9189
9190                                 speed = VectorLength(cl.movement_velocity);
9191
9192                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9193                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9194
9195                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9196                                 speed = bound(0, speed, 1);
9197                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9198
9199                                 // calculate values into a standard alpha
9200                                 cl.motionbluralpha = 1 - exp(-
9201                                                 (
9202                                                  (r_motionblur.value * speed / 80)
9203                                                  +
9204                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9205                                                 )
9206                                                 /
9207                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9208                                            );
9209
9210                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9211                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9212                                 // apply the blur
9213                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9214                                 {
9215                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9216                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9217                                         switch(vid.renderpath)
9218                                         {
9219                                         case RENDERPATH_GL11:
9220                                         case RENDERPATH_GL13:
9221                                         case RENDERPATH_GL20:
9222                                         case RENDERPATH_CGGL:
9223                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9224                                                 break;
9225                                         case RENDERPATH_D3D9:
9226                                         case RENDERPATH_D3D10:
9227                                         case RENDERPATH_D3D11:
9228                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9229                                                 break;
9230                                         }
9231                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9232                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9233                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9234                                 }
9235                         }
9236
9237                         // copy view into the screen texture
9238                         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);
9239                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9240                 }
9241                 else if (!r_bloomstate.texture_bloom)
9242                 {
9243                         // we may still have to do view tint...
9244                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9245                         {
9246                                 // apply a color tint to the whole view
9247                                 R_ResetViewRendering2D();
9248                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9249                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9250                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9251                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9252                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9253                         }
9254                         break; // no screen processing, no bloom, skip it
9255                 }
9256
9257                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9258                 {
9259                         // render simple bloom effect
9260                         // copy the screen and shrink it and darken it for the bloom process
9261                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9262                         // make the bloom texture
9263                         R_Bloom_MakeTexture();
9264                 }
9265
9266 #if _MSC_VER >= 1400
9267 #define sscanf sscanf_s
9268 #endif
9269                 memset(uservecs, 0, sizeof(uservecs));
9270                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9271                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9272                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9273                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9274
9275                 R_ResetViewRendering2D();
9276                 GL_Color(1, 1, 1, 1);
9277                 GL_BlendFunc(GL_ONE, GL_ZERO);
9278
9279                 switch(vid.renderpath)
9280                 {
9281                 case RENDERPATH_GL20:
9282                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9283                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9284                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9285                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9286                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9287                         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]);
9288                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9289                         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]);
9290                         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]);
9291                         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]);
9292                         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]);
9293                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9294                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9295                         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);
9296                         break;
9297                 case RENDERPATH_CGGL:
9298 #ifdef SUPPORTCG
9299                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9300                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9301                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9302                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9303                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9304                         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
9305                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9306                         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
9307                         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
9308                         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
9309                         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
9310                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9311                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9312                         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);
9313 #endif
9314                         break;
9315                 case RENDERPATH_D3D9:
9316 #ifdef SUPPORTD3D
9317                         // 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...
9318                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9319                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9320                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9321                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9322                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9323                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9324                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9325                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9326                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9327                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9328                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9329                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9330                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9331                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9332 #endif
9333                         break;
9334                 case RENDERPATH_D3D10:
9335                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9336                         break;
9337                 case RENDERPATH_D3D11:
9338                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9339                         break;
9340                 default:
9341                         break;
9342                 }
9343                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9344                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9345                 break;
9346         case RENDERPATH_GL13:
9347         case RENDERPATH_GL11:
9348                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9349                 {
9350                         // apply a color tint to the whole view
9351                         R_ResetViewRendering2D();
9352                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9353                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9354                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9355                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9356                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9357                 }
9358                 break;
9359         }
9360 }
9361
9362 matrix4x4_t r_waterscrollmatrix;
9363
9364 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9365 {
9366         if (r_refdef.fog_density)
9367         {
9368                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9369                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9370                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9371
9372                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9373                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9374                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9375                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9376
9377                 {
9378                         vec3_t fogvec;
9379                         VectorCopy(r_refdef.fogcolor, fogvec);
9380                         //   color.rgb *= ContrastBoost * SceneBrightness;
9381                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9382                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9383                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9384                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9385                 }
9386         }
9387 }
9388
9389 void R_UpdateVariables(void)
9390 {
9391         R_Textures_Frame();
9392
9393         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9394
9395         r_refdef.farclip = r_farclip_base.value;
9396         if (r_refdef.scene.worldmodel)
9397                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9398         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9399
9400         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9401                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9402         r_refdef.polygonfactor = 0;
9403         r_refdef.polygonoffset = 0;
9404         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9405         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9406
9407         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9408         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9409         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9410         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9411         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9412         if (r_showsurfaces.integer)
9413         {
9414                 r_refdef.scene.rtworld = false;
9415                 r_refdef.scene.rtworldshadows = false;
9416                 r_refdef.scene.rtdlight = false;
9417                 r_refdef.scene.rtdlightshadows = false;
9418                 r_refdef.lightmapintensity = 0;
9419         }
9420
9421         if (gamemode == GAME_NEHAHRA)
9422         {
9423                 if (gl_fogenable.integer)
9424                 {
9425                         r_refdef.oldgl_fogenable = true;
9426                         r_refdef.fog_density = gl_fogdensity.value;
9427                         r_refdef.fog_red = gl_fogred.value;
9428                         r_refdef.fog_green = gl_foggreen.value;
9429                         r_refdef.fog_blue = gl_fogblue.value;
9430                         r_refdef.fog_alpha = 1;
9431                         r_refdef.fog_start = 0;
9432                         r_refdef.fog_end = gl_skyclip.value;
9433                         r_refdef.fog_height = 1<<30;
9434                         r_refdef.fog_fadedepth = 128;
9435                 }
9436                 else if (r_refdef.oldgl_fogenable)
9437                 {
9438                         r_refdef.oldgl_fogenable = false;
9439                         r_refdef.fog_density = 0;
9440                         r_refdef.fog_red = 0;
9441                         r_refdef.fog_green = 0;
9442                         r_refdef.fog_blue = 0;
9443                         r_refdef.fog_alpha = 0;
9444                         r_refdef.fog_start = 0;
9445                         r_refdef.fog_end = 0;
9446                         r_refdef.fog_height = 1<<30;
9447                         r_refdef.fog_fadedepth = 128;
9448                 }
9449         }
9450
9451         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9452         r_refdef.fog_start = max(0, r_refdef.fog_start);
9453         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9454
9455         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9456
9457         if (r_refdef.fog_density && r_drawfog.integer)
9458         {
9459                 r_refdef.fogenabled = true;
9460                 // this is the point where the fog reaches 0.9986 alpha, which we
9461                 // consider a good enough cutoff point for the texture
9462                 // (0.9986 * 256 == 255.6)
9463                 if (r_fog_exp2.integer)
9464                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9465                 else
9466                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9467                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9468                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9469                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9470                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9471                         R_BuildFogHeightTexture();
9472                 // fog color was already set
9473                 // update the fog texture
9474                 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)
9475                         R_BuildFogTexture();
9476                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9477                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9478         }
9479         else
9480                 r_refdef.fogenabled = false;
9481
9482         switch(vid.renderpath)
9483         {
9484         case RENDERPATH_GL20:
9485         case RENDERPATH_CGGL:
9486         case RENDERPATH_D3D9:
9487         case RENDERPATH_D3D10:
9488         case RENDERPATH_D3D11:
9489                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9490                 {
9491                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9492                         {
9493                                 // build GLSL gamma texture
9494 #define RAMPWIDTH 256
9495                                 unsigned short ramp[RAMPWIDTH * 3];
9496                                 unsigned char rampbgr[RAMPWIDTH][4];
9497                                 int i;
9498
9499                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9500
9501                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9502                                 for(i = 0; i < RAMPWIDTH; ++i)
9503                                 {
9504                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9505                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9506                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9507                                         rampbgr[i][3] = 0;
9508                                 }
9509                                 if (r_texture_gammaramps)
9510                                 {
9511                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9512                                 }
9513                                 else
9514                                 {
9515                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9516                                 }
9517                         }
9518                 }
9519                 else
9520                 {
9521                         // remove GLSL gamma texture
9522                 }
9523                 break;
9524         case RENDERPATH_GL13:
9525         case RENDERPATH_GL11:
9526                 break;
9527         }
9528 }
9529
9530 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9531 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9532 /*
9533 ================
9534 R_SelectScene
9535 ================
9536 */
9537 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9538         if( scenetype != r_currentscenetype ) {
9539                 // store the old scenetype
9540                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9541                 r_currentscenetype = scenetype;
9542                 // move in the new scene
9543                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9544         }
9545 }
9546
9547 /*
9548 ================
9549 R_GetScenePointer
9550 ================
9551 */
9552 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9553 {
9554         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9555         if( scenetype == r_currentscenetype ) {
9556                 return &r_refdef.scene;
9557         } else {
9558                 return &r_scenes_store[ scenetype ];
9559         }
9560 }
9561
9562 /*
9563 ================
9564 R_RenderView
9565 ================
9566 */
9567 void R_RenderView(void)
9568 {
9569         if (r_timereport_active)
9570                 R_TimeReport("start");
9571         r_textureframe++; // used only by R_GetCurrentTexture
9572         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9573
9574         if (!r_drawentities.integer)
9575                 r_refdef.scene.numentities = 0;
9576
9577         R_AnimCache_ClearCache();
9578         R_FrameData_NewFrame();
9579
9580         if (r_refdef.view.isoverlay)
9581         {
9582                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9583                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9584                 R_TimeReport("depthclear");
9585
9586                 r_refdef.view.showdebug = false;
9587
9588                 r_waterstate.enabled = false;
9589                 r_waterstate.numwaterplanes = 0;
9590
9591                 R_RenderScene();
9592
9593                 CHECKGLERROR
9594                 return;
9595         }
9596
9597         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9598                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9599
9600         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9601
9602         R_RenderView_UpdateViewVectors();
9603
9604         R_Shadow_UpdateWorldLightSelection();
9605
9606         R_Bloom_StartFrame();
9607         R_Water_StartFrame();
9608
9609         CHECKGLERROR
9610         if (r_timereport_active)
9611                 R_TimeReport("viewsetup");
9612
9613         R_ResetViewRendering3D();
9614
9615         if (r_refdef.view.clear || r_refdef.fogenabled)
9616         {
9617                 R_ClearScreen(r_refdef.fogenabled);
9618                 if (r_timereport_active)
9619                         R_TimeReport("viewclear");
9620         }
9621         r_refdef.view.clear = true;
9622
9623         // this produces a bloom texture to be used in R_BlendView() later
9624         if (r_hdr.integer && r_bloomstate.bloomwidth)
9625         {
9626                 R_HDR_RenderBloomTexture();
9627                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9628                 r_textureframe++; // used only by R_GetCurrentTexture
9629         }
9630
9631         r_refdef.view.showdebug = true;
9632
9633         R_View_Update();
9634         if (r_timereport_active)
9635                 R_TimeReport("visibility");
9636
9637         r_waterstate.numwaterplanes = 0;
9638         if (r_waterstate.enabled)
9639                 R_RenderWaterPlanes();
9640
9641         R_RenderScene();
9642         r_waterstate.numwaterplanes = 0;
9643
9644         R_BlendView();
9645         if (r_timereport_active)
9646                 R_TimeReport("blendview");
9647
9648         GL_Scissor(0, 0, vid.width, vid.height);
9649         GL_ScissorTest(false);
9650         CHECKGLERROR
9651 }
9652
9653 void R_RenderWaterPlanes(void)
9654 {
9655         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9656         {
9657                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9658                 if (r_timereport_active)
9659                         R_TimeReport("waterworld");
9660         }
9661
9662         // don't let sound skip if going slow
9663         if (r_refdef.scene.extraupdate)
9664                 S_ExtraUpdate ();
9665
9666         R_DrawModelsAddWaterPlanes();
9667         if (r_timereport_active)
9668                 R_TimeReport("watermodels");
9669
9670         if (r_waterstate.numwaterplanes)
9671         {
9672                 R_Water_ProcessPlanes();
9673                 if (r_timereport_active)
9674                         R_TimeReport("waterscenes");
9675         }
9676 }
9677
9678 extern void R_DrawLightningBeams (void);
9679 extern void VM_CL_AddPolygonsToMeshQueue (void);
9680 extern void R_DrawPortals (void);
9681 extern cvar_t cl_locs_show;
9682 static void R_DrawLocs(void);
9683 static void R_DrawEntityBBoxes(void);
9684 static void R_DrawModelDecals(void);
9685 extern void R_DrawModelShadows(void);
9686 extern void R_DrawModelShadowMaps(void);
9687 extern cvar_t cl_decals_newsystem;
9688 extern qboolean r_shadow_usingdeferredprepass;
9689 void R_RenderScene(void)
9690 {
9691         qboolean shadowmapping = false;
9692
9693         if (r_timereport_active)
9694                 R_TimeReport("beginscene");
9695
9696         r_refdef.stats.renders++;
9697
9698         R_UpdateFogColor();
9699
9700         // don't let sound skip if going slow
9701         if (r_refdef.scene.extraupdate)
9702                 S_ExtraUpdate ();
9703
9704         R_MeshQueue_BeginScene();
9705
9706         R_SkyStartFrame();
9707
9708         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);
9709
9710         if (r_timereport_active)
9711                 R_TimeReport("skystartframe");
9712
9713         if (cl.csqc_vidvars.drawworld)
9714         {
9715                 // don't let sound skip if going slow
9716                 if (r_refdef.scene.extraupdate)
9717                         S_ExtraUpdate ();
9718
9719                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9720                 {
9721                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9722                         if (r_timereport_active)
9723                                 R_TimeReport("worldsky");
9724                 }
9725
9726                 if (R_DrawBrushModelsSky() && r_timereport_active)
9727                         R_TimeReport("bmodelsky");
9728
9729                 if (skyrendermasked && skyrenderlater)
9730                 {
9731                         // we have to force off the water clipping plane while rendering sky
9732                         R_SetupView(false);
9733                         R_Sky();
9734                         R_SetupView(true);
9735                         if (r_timereport_active)
9736                                 R_TimeReport("sky");
9737                 }
9738         }
9739
9740         R_AnimCache_CacheVisibleEntities();
9741         if (r_timereport_active)
9742                 R_TimeReport("animation");
9743
9744         R_Shadow_PrepareLights();
9745         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9746                 R_Shadow_PrepareModelShadows();
9747         if (r_timereport_active)
9748                 R_TimeReport("preparelights");
9749
9750         if (R_Shadow_ShadowMappingEnabled())
9751                 shadowmapping = true;
9752
9753         if (r_shadow_usingdeferredprepass)
9754                 R_Shadow_DrawPrepass();
9755
9756         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9757         {
9758                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9759                 if (r_timereport_active)
9760                         R_TimeReport("worlddepth");
9761         }
9762         if (r_depthfirst.integer >= 2)
9763         {
9764                 R_DrawModelsDepth();
9765                 if (r_timereport_active)
9766                         R_TimeReport("modeldepth");
9767         }
9768
9769         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9770         {
9771                 R_DrawModelShadowMaps();
9772                 R_ResetViewRendering3D();
9773                 // don't let sound skip if going slow
9774                 if (r_refdef.scene.extraupdate)
9775                         S_ExtraUpdate ();
9776         }
9777
9778         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9779         {
9780                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9781                 if (r_timereport_active)
9782                         R_TimeReport("world");
9783         }
9784
9785         // don't let sound skip if going slow
9786         if (r_refdef.scene.extraupdate)
9787                 S_ExtraUpdate ();
9788
9789         R_DrawModels();
9790         if (r_timereport_active)
9791                 R_TimeReport("models");
9792
9793         // don't let sound skip if going slow
9794         if (r_refdef.scene.extraupdate)
9795                 S_ExtraUpdate ();
9796
9797         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9798         {
9799                 R_DrawModelShadows();
9800                 R_ResetViewRendering3D();
9801                 // don't let sound skip if going slow
9802                 if (r_refdef.scene.extraupdate)
9803                         S_ExtraUpdate ();
9804         }
9805
9806         if (!r_shadow_usingdeferredprepass)
9807         {
9808                 R_Shadow_DrawLights();
9809                 if (r_timereport_active)
9810                         R_TimeReport("rtlights");
9811         }
9812
9813         // don't let sound skip if going slow
9814         if (r_refdef.scene.extraupdate)
9815                 S_ExtraUpdate ();
9816
9817         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9818         {
9819                 R_DrawModelShadows();
9820                 R_ResetViewRendering3D();
9821                 // don't let sound skip if going slow
9822                 if (r_refdef.scene.extraupdate)
9823                         S_ExtraUpdate ();
9824         }
9825
9826         if (cl.csqc_vidvars.drawworld)
9827         {
9828                 if (cl_decals_newsystem.integer)
9829                 {
9830                         R_DrawModelDecals();
9831                         if (r_timereport_active)
9832                                 R_TimeReport("modeldecals");
9833                 }
9834                 else
9835                 {
9836                         R_DrawDecals();
9837                         if (r_timereport_active)
9838                                 R_TimeReport("decals");
9839                 }
9840
9841                 R_DrawParticles();
9842                 if (r_timereport_active)
9843                         R_TimeReport("particles");
9844
9845                 R_DrawExplosions();
9846                 if (r_timereport_active)
9847                         R_TimeReport("explosions");
9848
9849                 R_DrawLightningBeams();
9850                 if (r_timereport_active)
9851                         R_TimeReport("lightning");
9852         }
9853
9854         VM_CL_AddPolygonsToMeshQueue();
9855
9856         if (r_refdef.view.showdebug)
9857         {
9858                 if (cl_locs_show.integer)
9859                 {
9860                         R_DrawLocs();
9861                         if (r_timereport_active)
9862                                 R_TimeReport("showlocs");
9863                 }
9864
9865                 if (r_drawportals.integer)
9866                 {
9867                         R_DrawPortals();
9868                         if (r_timereport_active)
9869                                 R_TimeReport("portals");
9870                 }
9871
9872                 if (r_showbboxes.value > 0)
9873                 {
9874                         R_DrawEntityBBoxes();
9875                         if (r_timereport_active)
9876                                 R_TimeReport("bboxes");
9877                 }
9878         }
9879
9880         R_MeshQueue_RenderTransparent();
9881         if (r_timereport_active)
9882                 R_TimeReport("drawtrans");
9883
9884         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))
9885         {
9886                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9887                 if (r_timereport_active)
9888                         R_TimeReport("worlddebug");
9889                 R_DrawModelsDebug();
9890                 if (r_timereport_active)
9891                         R_TimeReport("modeldebug");
9892         }
9893
9894         if (cl.csqc_vidvars.drawworld)
9895         {
9896                 R_Shadow_DrawCoronas();
9897                 if (r_timereport_active)
9898                         R_TimeReport("coronas");
9899         }
9900
9901         // don't let sound skip if going slow
9902         if (r_refdef.scene.extraupdate)
9903                 S_ExtraUpdate ();
9904
9905         R_ResetViewRendering2D();
9906 }
9907
9908 static const unsigned short bboxelements[36] =
9909 {
9910         5, 1, 3, 5, 3, 7,
9911         6, 2, 0, 6, 0, 4,
9912         7, 3, 2, 7, 2, 6,
9913         4, 0, 1, 4, 1, 5,
9914         4, 5, 7, 4, 7, 6,
9915         1, 0, 2, 1, 2, 3,
9916 };
9917
9918 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9919 {
9920         int i;
9921         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9922
9923         RSurf_ActiveWorldEntity();
9924
9925         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9926         GL_DepthMask(false);
9927         GL_DepthRange(0, 1);
9928         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9929         R_Mesh_ResetTextureState();
9930
9931         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9932         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9933         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9934         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9935         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9936         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9937         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9938         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9939         R_FillColors(color4f, 8, cr, cg, cb, ca);
9940         if (r_refdef.fogenabled)
9941         {
9942                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9943                 {
9944                         f1 = RSurf_FogVertex(v);
9945                         f2 = 1 - f1;
9946                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9947                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9948                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9949                 }
9950         }
9951         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9952         R_Mesh_ResetTextureState();
9953         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9954         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9955 }
9956
9957 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9958 {
9959         int i;
9960         float color[4];
9961         prvm_edict_t *edict;
9962         prvm_prog_t *prog_save = prog;
9963
9964         // this function draws bounding boxes of server entities
9965         if (!sv.active)
9966                 return;
9967
9968         GL_CullFace(GL_NONE);
9969         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9970
9971         prog = 0;
9972         SV_VM_Begin();
9973         for (i = 0;i < numsurfaces;i++)
9974         {
9975                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9976                 switch ((int)edict->fields.server->solid)
9977                 {
9978                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9979                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9980                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9981                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9982                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9983                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9984                 }
9985                 color[3] *= r_showbboxes.value;
9986                 color[3] = bound(0, color[3], 1);
9987                 GL_DepthTest(!r_showdisabledepthtest.integer);
9988                 GL_CullFace(r_refdef.view.cullface_front);
9989                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9990         }
9991         SV_VM_End();
9992         prog = prog_save;
9993 }
9994
9995 static void R_DrawEntityBBoxes(void)
9996 {
9997         int i;
9998         prvm_edict_t *edict;
9999         vec3_t center;
10000         prvm_prog_t *prog_save = prog;
10001
10002         // this function draws bounding boxes of server entities
10003         if (!sv.active)
10004                 return;
10005
10006         prog = 0;
10007         SV_VM_Begin();
10008         for (i = 0;i < prog->num_edicts;i++)
10009         {
10010                 edict = PRVM_EDICT_NUM(i);
10011                 if (edict->priv.server->free)
10012                         continue;
10013                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10014                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10015                         continue;
10016                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10017                         continue;
10018                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10019                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10020         }
10021         SV_VM_End();
10022         prog = prog_save;
10023 }
10024
10025 static const int nomodelelement3i[24] =
10026 {
10027         5, 2, 0,
10028         5, 1, 2,
10029         5, 0, 3,
10030         5, 3, 1,
10031         0, 2, 4,
10032         2, 1, 4,
10033         3, 0, 4,
10034         1, 3, 4
10035 };
10036
10037 static const unsigned short nomodelelement3s[24] =
10038 {
10039         5, 2, 0,
10040         5, 1, 2,
10041         5, 0, 3,
10042         5, 3, 1,
10043         0, 2, 4,
10044         2, 1, 4,
10045         3, 0, 4,
10046         1, 3, 4
10047 };
10048
10049 static const float nomodelvertex3f[6*3] =
10050 {
10051         -16,   0,   0,
10052          16,   0,   0,
10053           0, -16,   0,
10054           0,  16,   0,
10055           0,   0, -16,
10056           0,   0,  16
10057 };
10058
10059 static const float nomodelcolor4f[6*4] =
10060 {
10061         0.0f, 0.0f, 0.5f, 1.0f,
10062         0.0f, 0.0f, 0.5f, 1.0f,
10063         0.0f, 0.5f, 0.0f, 1.0f,
10064         0.0f, 0.5f, 0.0f, 1.0f,
10065         0.5f, 0.0f, 0.0f, 1.0f,
10066         0.5f, 0.0f, 0.0f, 1.0f
10067 };
10068
10069 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10070 {
10071         int i;
10072         float f1, f2, *c;
10073         float color4f[6*4];
10074
10075         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);
10076
10077         // this is only called once per entity so numsurfaces is always 1, and
10078         // surfacelist is always {0}, so this code does not handle batches
10079
10080         if (rsurface.ent_flags & RENDER_ADDITIVE)
10081         {
10082                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10083                 GL_DepthMask(false);
10084         }
10085         else if (rsurface.colormod[3] < 1)
10086         {
10087                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10088                 GL_DepthMask(false);
10089         }
10090         else
10091         {
10092                 GL_BlendFunc(GL_ONE, GL_ZERO);
10093                 GL_DepthMask(true);
10094         }
10095         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10096         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10097         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10098         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10099         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10100         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10101         for (i = 0, c = color4f;i < 6;i++, c += 4)
10102         {
10103                 c[0] *= rsurface.colormod[0];
10104                 c[1] *= rsurface.colormod[1];
10105                 c[2] *= rsurface.colormod[2];
10106                 c[3] *= rsurface.colormod[3];
10107         }
10108         if (r_refdef.fogenabled)
10109         {
10110                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10111                 {
10112                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10113                         f2 = 1 - f1;
10114                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10115                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10116                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10117                 }
10118         }
10119         R_Mesh_ResetTextureState();
10120         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10121         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10122 }
10123
10124 void R_DrawNoModel(entity_render_t *ent)
10125 {
10126         vec3_t org;
10127         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10128         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10129                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10130         else
10131                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10132 }
10133
10134 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10135 {
10136         vec3_t right1, right2, diff, normal;
10137
10138         VectorSubtract (org2, org1, normal);
10139
10140         // calculate 'right' vector for start
10141         VectorSubtract (r_refdef.view.origin, org1, diff);
10142         CrossProduct (normal, diff, right1);
10143         VectorNormalize (right1);
10144
10145         // calculate 'right' vector for end
10146         VectorSubtract (r_refdef.view.origin, org2, diff);
10147         CrossProduct (normal, diff, right2);
10148         VectorNormalize (right2);
10149
10150         vert[ 0] = org1[0] + width * right1[0];
10151         vert[ 1] = org1[1] + width * right1[1];
10152         vert[ 2] = org1[2] + width * right1[2];
10153         vert[ 3] = org1[0] - width * right1[0];
10154         vert[ 4] = org1[1] - width * right1[1];
10155         vert[ 5] = org1[2] - width * right1[2];
10156         vert[ 6] = org2[0] - width * right2[0];
10157         vert[ 7] = org2[1] - width * right2[1];
10158         vert[ 8] = org2[2] - width * right2[2];
10159         vert[ 9] = org2[0] + width * right2[0];
10160         vert[10] = org2[1] + width * right2[1];
10161         vert[11] = org2[2] + width * right2[2];
10162 }
10163
10164 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)
10165 {
10166         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10167         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10168         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10169         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10170         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10171         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10172         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10173         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10174         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10175         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10176         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10177         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10178 }
10179
10180 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10181 {
10182         int i;
10183         float *vertex3f;
10184         float v[3];
10185         VectorSet(v, x, y, z);
10186         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10187                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10188                         break;
10189         if (i == mesh->numvertices)
10190         {
10191                 if (mesh->numvertices < mesh->maxvertices)
10192                 {
10193                         VectorCopy(v, vertex3f);
10194                         mesh->numvertices++;
10195                 }
10196                 return mesh->numvertices;
10197         }
10198         else
10199                 return i;
10200 }
10201
10202 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10203 {
10204         int i;
10205         int *e, element[3];
10206         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10207         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10208         e = mesh->element3i + mesh->numtriangles * 3;
10209         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10210         {
10211                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10212                 if (mesh->numtriangles < mesh->maxtriangles)
10213                 {
10214                         *e++ = element[0];
10215                         *e++ = element[1];
10216                         *e++ = element[2];
10217                         mesh->numtriangles++;
10218                 }
10219                 element[1] = element[2];
10220         }
10221 }
10222
10223 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10224 {
10225         int i;
10226         int *e, element[3];
10227         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10228         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10229         e = mesh->element3i + mesh->numtriangles * 3;
10230         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10231         {
10232                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10233                 if (mesh->numtriangles < mesh->maxtriangles)
10234                 {
10235                         *e++ = element[0];
10236                         *e++ = element[1];
10237                         *e++ = element[2];
10238                         mesh->numtriangles++;
10239                 }
10240                 element[1] = element[2];
10241         }
10242 }
10243
10244 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10245 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10246 {
10247         int planenum, planenum2;
10248         int w;
10249         int tempnumpoints;
10250         mplane_t *plane, *plane2;
10251         double maxdist;
10252         double temppoints[2][256*3];
10253         // figure out how large a bounding box we need to properly compute this brush
10254         maxdist = 0;
10255         for (w = 0;w < numplanes;w++)
10256                 maxdist = max(maxdist, fabs(planes[w].dist));
10257         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10258         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10259         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10260         {
10261                 w = 0;
10262                 tempnumpoints = 4;
10263                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10264                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10265                 {
10266                         if (planenum2 == planenum)
10267                                 continue;
10268                         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);
10269                         w = !w;
10270                 }
10271                 if (tempnumpoints < 3)
10272                         continue;
10273                 // generate elements forming a triangle fan for this polygon
10274                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10275         }
10276 }
10277
10278 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)
10279 {
10280         texturelayer_t *layer;
10281         layer = t->currentlayers + t->currentnumlayers++;
10282         layer->type = type;
10283         layer->depthmask = depthmask;
10284         layer->blendfunc1 = blendfunc1;
10285         layer->blendfunc2 = blendfunc2;
10286         layer->texture = texture;
10287         layer->texmatrix = *matrix;
10288         layer->color[0] = r;
10289         layer->color[1] = g;
10290         layer->color[2] = b;
10291         layer->color[3] = a;
10292 }
10293
10294 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10295 {
10296         if(parms[0] == 0 && parms[1] == 0)
10297                 return false;
10298         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10299                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10300                         return false;
10301         return true;
10302 }
10303
10304 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10305 {
10306         double index, f;
10307         index = parms[2] + r_refdef.scene.time * parms[3];
10308         index -= floor(index);
10309         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10310         {
10311         default:
10312         case Q3WAVEFUNC_NONE:
10313         case Q3WAVEFUNC_NOISE:
10314         case Q3WAVEFUNC_COUNT:
10315                 f = 0;
10316                 break;
10317         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10318         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10319         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10320         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10321         case Q3WAVEFUNC_TRIANGLE:
10322                 index *= 4;
10323                 f = index - floor(index);
10324                 if (index < 1)
10325                         f = f;
10326                 else if (index < 2)
10327                         f = 1 - f;
10328                 else if (index < 3)
10329                         f = -f;
10330                 else
10331                         f = -(1 - f);
10332                 break;
10333         }
10334         f = parms[0] + parms[1] * f;
10335         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10336                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10337         return (float) f;
10338 }
10339
10340 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10341 {
10342         int w, h, idx;
10343         float f;
10344         float tcmat[12];
10345         matrix4x4_t matrix, temp;
10346         switch(tcmod->tcmod)
10347         {
10348                 case Q3TCMOD_COUNT:
10349                 case Q3TCMOD_NONE:
10350                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10351                                 matrix = r_waterscrollmatrix;
10352                         else
10353                                 matrix = identitymatrix;
10354                         break;
10355                 case Q3TCMOD_ENTITYTRANSLATE:
10356                         // this is used in Q3 to allow the gamecode to control texcoord
10357                         // scrolling on the entity, which is not supported in darkplaces yet.
10358                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10359                         break;
10360                 case Q3TCMOD_ROTATE:
10361                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10362                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10363                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10364                         break;
10365                 case Q3TCMOD_SCALE:
10366                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10367                         break;
10368                 case Q3TCMOD_SCROLL:
10369                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10370                         break;
10371                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10372                         w = (int) tcmod->parms[0];
10373                         h = (int) tcmod->parms[1];
10374                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10375                         f = f - floor(f);
10376                         idx = (int) floor(f * w * h);
10377                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10378                         break;
10379                 case Q3TCMOD_STRETCH:
10380                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10381                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10382                         break;
10383                 case Q3TCMOD_TRANSFORM:
10384                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10385                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10386                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10387                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10388                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10389                         break;
10390                 case Q3TCMOD_TURBULENT:
10391                         // this is handled in the RSurf_PrepareVertices function
10392                         matrix = identitymatrix;
10393                         break;
10394         }
10395         temp = *texmatrix;
10396         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10397 }
10398
10399 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10400 {
10401         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10402         char name[MAX_QPATH];
10403         skinframe_t *skinframe;
10404         unsigned char pixels[296*194];
10405         strlcpy(cache->name, skinname, sizeof(cache->name));
10406         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10407         if (developer_loading.integer)
10408                 Con_Printf("loading %s\n", name);
10409         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10410         if (!skinframe || !skinframe->base)
10411         {
10412                 unsigned char *f;
10413                 fs_offset_t filesize;
10414                 skinframe = NULL;
10415                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10416                 if (f)
10417                 {
10418                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10419                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10420                         Mem_Free(f);
10421                 }
10422         }
10423         cache->skinframe = skinframe;
10424 }
10425
10426 texture_t *R_GetCurrentTexture(texture_t *t)
10427 {
10428         int i;
10429         const entity_render_t *ent = rsurface.entity;
10430         dp_model_t *model = ent->model;
10431         q3shaderinfo_layer_tcmod_t *tcmod;
10432
10433         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10434                 return t->currentframe;
10435         t->update_lastrenderframe = r_textureframe;
10436         t->update_lastrenderentity = (void *)ent;
10437
10438         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10439                 t->camera_entity = ent->entitynumber;
10440         else
10441                 t->camera_entity = 0;
10442
10443         // switch to an alternate material if this is a q1bsp animated material
10444         {
10445                 texture_t *texture = t;
10446                 int s = rsurface.ent_skinnum;
10447                 if ((unsigned int)s >= (unsigned int)model->numskins)
10448                         s = 0;
10449                 if (model->skinscenes)
10450                 {
10451                         if (model->skinscenes[s].framecount > 1)
10452                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10453                         else
10454                                 s = model->skinscenes[s].firstframe;
10455                 }
10456                 if (s > 0)
10457                         t = t + s * model->num_surfaces;
10458                 if (t->animated)
10459                 {
10460                         // use an alternate animation if the entity's frame is not 0,
10461                         // and only if the texture has an alternate animation
10462                         if (rsurface.ent_alttextures && t->anim_total[1])
10463                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10464                         else
10465                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10466                 }
10467                 texture->currentframe = t;
10468         }
10469
10470         // update currentskinframe to be a qw skin or animation frame
10471         if (rsurface.ent_qwskin >= 0)
10472         {
10473                 i = rsurface.ent_qwskin;
10474                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10475                 {
10476                         r_qwskincache_size = cl.maxclients;
10477                         if (r_qwskincache)
10478                                 Mem_Free(r_qwskincache);
10479                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10480                 }
10481                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10482                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10483                 t->currentskinframe = r_qwskincache[i].skinframe;
10484                 if (t->currentskinframe == NULL)
10485                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10486         }
10487         else if (t->numskinframes >= 2)
10488                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10489         if (t->backgroundnumskinframes >= 2)
10490                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10491
10492         t->currentmaterialflags = t->basematerialflags;
10493         t->currentalpha = rsurface.colormod[3];
10494         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10495                 t->currentalpha *= r_wateralpha.value;
10496         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10497                 t->currentalpha *= t->r_water_wateralpha;
10498         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10499                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10500         if (!(rsurface.ent_flags & RENDER_LIGHT))
10501                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10502         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10503         {
10504                 // pick a model lighting mode
10505                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10506                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10507                 else
10508                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10509         }
10510         if (rsurface.ent_flags & RENDER_ADDITIVE)
10511                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10512         else if (t->currentalpha < 1)
10513                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10514         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10515                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10516         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10517                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10518         if (t->backgroundnumskinframes)
10519                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10520         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10521         {
10522                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10523                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10524         }
10525         else
10526                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10527         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10528                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10529
10530         // there is no tcmod
10531         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10532         {
10533                 t->currenttexmatrix = r_waterscrollmatrix;
10534                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10535         }
10536         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10537         {
10538                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10539                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10540         }
10541
10542         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10543                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10544         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10545                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10546
10547         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10548         if (t->currentskinframe->qpixels)
10549                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10550         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10551         if (!t->basetexture)
10552                 t->basetexture = r_texture_notexture;
10553         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10554         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10555         t->nmaptexture = t->currentskinframe->nmap;
10556         if (!t->nmaptexture)
10557                 t->nmaptexture = r_texture_blanknormalmap;
10558         t->glosstexture = r_texture_black;
10559         t->glowtexture = t->currentskinframe->glow;
10560         t->fogtexture = t->currentskinframe->fog;
10561         t->reflectmasktexture = t->currentskinframe->reflect;
10562         if (t->backgroundnumskinframes)
10563         {
10564                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10565                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10566                 t->backgroundglosstexture = r_texture_black;
10567                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10568                 if (!t->backgroundnmaptexture)
10569                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10570         }
10571         else
10572         {
10573                 t->backgroundbasetexture = r_texture_white;
10574                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10575                 t->backgroundglosstexture = r_texture_black;
10576                 t->backgroundglowtexture = NULL;
10577         }
10578         t->specularpower = r_shadow_glossexponent.value;
10579         // TODO: store reference values for these in the texture?
10580         t->specularscale = 0;
10581         if (r_shadow_gloss.integer > 0)
10582         {
10583                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10584                 {
10585                         if (r_shadow_glossintensity.value > 0)
10586                         {
10587                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10588                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10589                                 t->specularscale = r_shadow_glossintensity.value;
10590                         }
10591                 }
10592                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10593                 {
10594                         t->glosstexture = r_texture_white;
10595                         t->backgroundglosstexture = r_texture_white;
10596                         t->specularscale = r_shadow_gloss2intensity.value;
10597                         t->specularpower = r_shadow_gloss2exponent.value;
10598                 }
10599         }
10600         t->specularscale *= t->specularscalemod;
10601         t->specularpower *= t->specularpowermod;
10602
10603         // lightmaps mode looks bad with dlights using actual texturing, so turn
10604         // off the colormap and glossmap, but leave the normalmap on as it still
10605         // accurately represents the shading involved
10606         if (gl_lightmaps.integer)
10607         {
10608                 t->basetexture = r_texture_grey128;
10609                 t->pantstexture = r_texture_black;
10610                 t->shirttexture = r_texture_black;
10611                 t->nmaptexture = r_texture_blanknormalmap;
10612                 t->glosstexture = r_texture_black;
10613                 t->glowtexture = NULL;
10614                 t->fogtexture = NULL;
10615                 t->reflectmasktexture = NULL;
10616                 t->backgroundbasetexture = NULL;
10617                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10618                 t->backgroundglosstexture = r_texture_black;
10619                 t->backgroundglowtexture = NULL;
10620                 t->specularscale = 0;
10621                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10622         }
10623
10624         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10625         VectorClear(t->dlightcolor);
10626         t->currentnumlayers = 0;
10627         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10628         {
10629                 int blendfunc1, blendfunc2;
10630                 qboolean depthmask;
10631                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10632                 {
10633                         blendfunc1 = GL_SRC_ALPHA;
10634                         blendfunc2 = GL_ONE;
10635                 }
10636                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10637                 {
10638                         blendfunc1 = GL_SRC_ALPHA;
10639                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10640                 }
10641                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10642                 {
10643                         blendfunc1 = t->customblendfunc[0];
10644                         blendfunc2 = t->customblendfunc[1];
10645                 }
10646                 else
10647                 {
10648                         blendfunc1 = GL_ONE;
10649                         blendfunc2 = GL_ZERO;
10650                 }
10651                 // don't colormod evilblend textures
10652                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10653                         VectorSet(t->lightmapcolor, 1, 1, 1);
10654                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10655                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10656                 {
10657                         // fullbright is not affected by r_refdef.lightmapintensity
10658                         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]);
10659                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10660                                 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]);
10661                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10662                                 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]);
10663                 }
10664                 else
10665                 {
10666                         vec3_t ambientcolor;
10667                         float colorscale;
10668                         // set the color tint used for lights affecting this surface
10669                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10670                         colorscale = 2;
10671                         // q3bsp has no lightmap updates, so the lightstylevalue that
10672                         // would normally be baked into the lightmap must be
10673                         // applied to the color
10674                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10675                         if (model->type == mod_brushq3)
10676                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10677                         colorscale *= r_refdef.lightmapintensity;
10678                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10679                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10680                         // basic lit geometry
10681                         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]);
10682                         // add pants/shirt if needed
10683                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10684                                 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]);
10685                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10686                                 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]);
10687                         // now add ambient passes if needed
10688                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10689                         {
10690                                 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]);
10691                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10692                                         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]);
10693                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10694                                         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]);
10695                         }
10696                 }
10697                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10698                         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]);
10699                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10700                 {
10701                         // if this is opaque use alpha blend which will darken the earlier
10702                         // passes cheaply.
10703                         //
10704                         // if this is an alpha blended material, all the earlier passes
10705                         // were darkened by fog already, so we only need to add the fog
10706                         // color ontop through the fog mask texture
10707                         //
10708                         // if this is an additive blended material, all the earlier passes
10709                         // were darkened by fog already, and we should not add fog color
10710                         // (because the background was not darkened, there is no fog color
10711                         // that was lost behind it).
10712                         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]);
10713                 }
10714         }
10715
10716         return t->currentframe;
10717 }
10718
10719 rsurfacestate_t rsurface;
10720
10721 void R_Mesh_ResizeArrays(int newvertices)
10722 {
10723         unsigned char *base;
10724         size_t size;
10725         if (rsurface.array_size >= newvertices)
10726                 return;
10727         if (rsurface.array_base)
10728                 Mem_Free(rsurface.array_base);
10729         rsurface.array_size = (newvertices + 1023) & ~1023;
10730         size = 0;
10731         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10732         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10733         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10734         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10735         size += rsurface.array_size * sizeof(float[3]);
10736         size += rsurface.array_size * sizeof(float[3]);
10737         size += rsurface.array_size * sizeof(float[3]);
10738         size += rsurface.array_size * sizeof(float[3]);
10739         size += rsurface.array_size * sizeof(float[3]);
10740         size += rsurface.array_size * sizeof(float[3]);
10741         size += rsurface.array_size * sizeof(float[3]);
10742         size += rsurface.array_size * sizeof(float[3]);
10743         size += rsurface.array_size * sizeof(float[4]);
10744         size += rsurface.array_size * sizeof(float[2]);
10745         size += rsurface.array_size * sizeof(float[2]);
10746         size += rsurface.array_size * sizeof(float[4]);
10747         size += rsurface.array_size * sizeof(int[3]);
10748         size += rsurface.array_size * sizeof(unsigned short[3]);
10749         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10750         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10751         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10752         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10753         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10754         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10755         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10756         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10757         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10758         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10759         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10760         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10761         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10762         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10763         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10764         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10765         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10766         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10767         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10768 }
10769
10770 void RSurf_ActiveWorldEntity(void)
10771 {
10772         dp_model_t *model = r_refdef.scene.worldmodel;
10773         //if (rsurface.entity == r_refdef.scene.worldentity)
10774         //      return;
10775         rsurface.entity = r_refdef.scene.worldentity;
10776         rsurface.skeleton = NULL;
10777         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10778         rsurface.ent_skinnum = 0;
10779         rsurface.ent_qwskin = -1;
10780         rsurface.ent_shadertime = 0;
10781         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10782         if (rsurface.array_size < model->surfmesh.num_vertices)
10783                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10784         rsurface.matrix = identitymatrix;
10785         rsurface.inversematrix = identitymatrix;
10786         rsurface.matrixscale = 1;
10787         rsurface.inversematrixscale = 1;
10788         R_EntityMatrix(&identitymatrix);
10789         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10790         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10791         rsurface.fograngerecip = r_refdef.fograngerecip;
10792         rsurface.fogheightfade = r_refdef.fogheightfade;
10793         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10794         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10795         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10796         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10797         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10798         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10799         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10800         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10801         rsurface.colormod[3] = 1;
10802         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);
10803         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10804         rsurface.frameblend[0].lerp = 1;
10805         rsurface.ent_alttextures = false;
10806         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10807         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10808         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10809         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10810         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10811         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10812         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10813         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10814         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10815         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10816         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10817         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10818         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10819         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10820         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10821         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10822         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10823         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10824         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10825         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10826         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10827         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10828         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10829         rsurface.modelelement3i = model->surfmesh.data_element3i;
10830         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10831         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10832         rsurface.modelelement3s = model->surfmesh.data_element3s;
10833         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10834         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10835         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10836         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10837         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10838         rsurface.modelsurfaces = model->data_surfaces;
10839         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10840         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10841         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10842         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10843         rsurface.modelgeneratedvertex = false;
10844         rsurface.batchgeneratedvertex = false;
10845         rsurface.batchfirstvertex = 0;
10846         rsurface.batchnumvertices = 0;
10847         rsurface.batchfirsttriangle = 0;
10848         rsurface.batchnumtriangles = 0;
10849         rsurface.batchvertex3f  = NULL;
10850         rsurface.batchvertex3f_vertexbuffer = NULL;
10851         rsurface.batchvertex3f_bufferoffset = 0;
10852         rsurface.batchsvector3f = NULL;
10853         rsurface.batchsvector3f_vertexbuffer = NULL;
10854         rsurface.batchsvector3f_bufferoffset = 0;
10855         rsurface.batchtvector3f = NULL;
10856         rsurface.batchtvector3f_vertexbuffer = NULL;
10857         rsurface.batchtvector3f_bufferoffset = 0;
10858         rsurface.batchnormal3f  = NULL;
10859         rsurface.batchnormal3f_vertexbuffer = NULL;
10860         rsurface.batchnormal3f_bufferoffset = 0;
10861         rsurface.batchlightmapcolor4f = NULL;
10862         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10863         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10864         rsurface.batchtexcoordtexture2f = NULL;
10865         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10866         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10867         rsurface.batchtexcoordlightmap2f = NULL;
10868         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10869         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10870         rsurface.batchvertexmesh = NULL;
10871         rsurface.batchvertexmeshbuffer = NULL;
10872         rsurface.batchvertexposition = NULL;
10873         rsurface.batchvertexpositionbuffer = NULL;
10874         rsurface.batchelement3i = NULL;
10875         rsurface.batchelement3i_indexbuffer = NULL;
10876         rsurface.batchelement3i_bufferoffset = 0;
10877         rsurface.batchelement3s = NULL;
10878         rsurface.batchelement3s_indexbuffer = NULL;
10879         rsurface.batchelement3s_bufferoffset = 0;
10880         rsurface.passcolor4f = NULL;
10881         rsurface.passcolor4f_vertexbuffer = NULL;
10882         rsurface.passcolor4f_bufferoffset = 0;
10883 }
10884
10885 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10886 {
10887         dp_model_t *model = ent->model;
10888         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10889         //      return;
10890         rsurface.entity = (entity_render_t *)ent;
10891         rsurface.skeleton = ent->skeleton;
10892         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10893         rsurface.ent_skinnum = ent->skinnum;
10894         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;
10895         rsurface.ent_shadertime = ent->shadertime;
10896         rsurface.ent_flags = ent->flags;
10897         if (rsurface.array_size < model->surfmesh.num_vertices)
10898                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10899         rsurface.matrix = ent->matrix;
10900         rsurface.inversematrix = ent->inversematrix;
10901         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10902         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10903         R_EntityMatrix(&rsurface.matrix);
10904         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10905         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10906         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10907         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10908         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10909         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10910         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10911         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10912         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10913         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10914         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10915         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10916         rsurface.colormod[3] = ent->alpha;
10917         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10918         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10919         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10920         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10921         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10922         if (ent->model->brush.submodel && !prepass)
10923         {
10924                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10925                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10926         }
10927         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10928         {
10929                 if (ent->animcache_vertex3f && !r_framedata_failed)
10930                 {
10931                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10932                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10933                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10934                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10935                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10936                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10937                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10938                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10939                 }
10940                 else if (wanttangents)
10941                 {
10942                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10943                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10944                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10945                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10946                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10947                         rsurface.modelvertexmesh = NULL;
10948                         rsurface.modelvertexmeshbuffer = NULL;
10949                         rsurface.modelvertexposition = NULL;
10950                         rsurface.modelvertexpositionbuffer = NULL;
10951                 }
10952                 else if (wantnormals)
10953                 {
10954                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10955                         rsurface.modelsvector3f = NULL;
10956                         rsurface.modeltvector3f = NULL;
10957                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10958                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10959                         rsurface.modelvertexmesh = NULL;
10960                         rsurface.modelvertexmeshbuffer = NULL;
10961                         rsurface.modelvertexposition = NULL;
10962                         rsurface.modelvertexpositionbuffer = NULL;
10963                 }
10964                 else
10965                 {
10966                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10967                         rsurface.modelsvector3f = NULL;
10968                         rsurface.modeltvector3f = NULL;
10969                         rsurface.modelnormal3f = NULL;
10970                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10971                         rsurface.modelvertexmesh = NULL;
10972                         rsurface.modelvertexmeshbuffer = NULL;
10973                         rsurface.modelvertexposition = NULL;
10974                         rsurface.modelvertexpositionbuffer = NULL;
10975                 }
10976                 rsurface.modelvertex3f_vertexbuffer = 0;
10977                 rsurface.modelvertex3f_bufferoffset = 0;
10978                 rsurface.modelsvector3f_vertexbuffer = 0;
10979                 rsurface.modelsvector3f_bufferoffset = 0;
10980                 rsurface.modeltvector3f_vertexbuffer = 0;
10981                 rsurface.modeltvector3f_bufferoffset = 0;
10982                 rsurface.modelnormal3f_vertexbuffer = 0;
10983                 rsurface.modelnormal3f_bufferoffset = 0;
10984                 rsurface.modelgeneratedvertex = true;
10985         }
10986         else
10987         {
10988                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10989                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10990                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10991                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10992                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10993                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10994                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10995                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10996                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10997                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10998                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10999                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11000                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11001                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11002                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11003                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11004                 rsurface.modelgeneratedvertex = false;
11005         }
11006         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11007         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11008         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11009         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11010         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11011         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11012         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11013         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11014         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11015         rsurface.modelelement3i = model->surfmesh.data_element3i;
11016         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11017         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11018         rsurface.modelelement3s = model->surfmesh.data_element3s;
11019         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11020         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11021         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11022         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11023         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11024         rsurface.modelsurfaces = model->data_surfaces;
11025         rsurface.batchgeneratedvertex = false;
11026         rsurface.batchfirstvertex = 0;
11027         rsurface.batchnumvertices = 0;
11028         rsurface.batchfirsttriangle = 0;
11029         rsurface.batchnumtriangles = 0;
11030         rsurface.batchvertex3f  = NULL;
11031         rsurface.batchvertex3f_vertexbuffer = NULL;
11032         rsurface.batchvertex3f_bufferoffset = 0;
11033         rsurface.batchsvector3f = NULL;
11034         rsurface.batchsvector3f_vertexbuffer = NULL;
11035         rsurface.batchsvector3f_bufferoffset = 0;
11036         rsurface.batchtvector3f = NULL;
11037         rsurface.batchtvector3f_vertexbuffer = NULL;
11038         rsurface.batchtvector3f_bufferoffset = 0;
11039         rsurface.batchnormal3f  = NULL;
11040         rsurface.batchnormal3f_vertexbuffer = NULL;
11041         rsurface.batchnormal3f_bufferoffset = 0;
11042         rsurface.batchlightmapcolor4f = NULL;
11043         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11044         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11045         rsurface.batchtexcoordtexture2f = NULL;
11046         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11047         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11048         rsurface.batchtexcoordlightmap2f = NULL;
11049         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11050         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11051         rsurface.batchvertexmesh = NULL;
11052         rsurface.batchvertexmeshbuffer = NULL;
11053         rsurface.batchvertexposition = NULL;
11054         rsurface.batchvertexpositionbuffer = NULL;
11055         rsurface.batchelement3i = NULL;
11056         rsurface.batchelement3i_indexbuffer = NULL;
11057         rsurface.batchelement3i_bufferoffset = 0;
11058         rsurface.batchelement3s = NULL;
11059         rsurface.batchelement3s_indexbuffer = NULL;
11060         rsurface.batchelement3s_bufferoffset = 0;
11061         rsurface.passcolor4f = NULL;
11062         rsurface.passcolor4f_vertexbuffer = NULL;
11063         rsurface.passcolor4f_bufferoffset = 0;
11064 }
11065
11066 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)
11067 {
11068         int i;
11069
11070         rsurface.entity = r_refdef.scene.worldentity;
11071         rsurface.skeleton = NULL;
11072         rsurface.ent_skinnum = 0;
11073         rsurface.ent_qwskin = -1;
11074         rsurface.ent_shadertime = shadertime;
11075         rsurface.ent_flags = entflags;
11076         rsurface.modelnumvertices = numvertices;
11077         rsurface.modelnumtriangles = numtriangles;
11078         if (rsurface.array_size < rsurface.modelnumvertices)
11079                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11080         rsurface.matrix = *matrix;
11081         rsurface.inversematrix = *inversematrix;
11082         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11083         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11084         R_EntityMatrix(&rsurface.matrix);
11085         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11086         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11087         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11088         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11089         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11090         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11091         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11092         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11093         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11094         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11095         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11096         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11097         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);
11098         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11099         rsurface.frameblend[0].lerp = 1;
11100         rsurface.ent_alttextures = false;
11101         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11102         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11103         if (wanttangents)
11104         {
11105                 rsurface.modelvertex3f = vertex3f;
11106                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11107                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11108                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11109         }
11110         else if (wantnormals)
11111         {
11112                 rsurface.modelvertex3f = vertex3f;
11113                 rsurface.modelsvector3f = NULL;
11114                 rsurface.modeltvector3f = NULL;
11115                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11116         }
11117         else
11118         {
11119                 rsurface.modelvertex3f = vertex3f;
11120                 rsurface.modelsvector3f = NULL;
11121                 rsurface.modeltvector3f = NULL;
11122                 rsurface.modelnormal3f = NULL;
11123         }
11124         rsurface.modelvertexmesh = NULL;
11125         rsurface.modelvertexmeshbuffer = NULL;
11126         rsurface.modelvertexposition = NULL;
11127         rsurface.modelvertexpositionbuffer = NULL;
11128         rsurface.modelvertex3f_vertexbuffer = 0;
11129         rsurface.modelvertex3f_bufferoffset = 0;
11130         rsurface.modelsvector3f_vertexbuffer = 0;
11131         rsurface.modelsvector3f_bufferoffset = 0;
11132         rsurface.modeltvector3f_vertexbuffer = 0;
11133         rsurface.modeltvector3f_bufferoffset = 0;
11134         rsurface.modelnormal3f_vertexbuffer = 0;
11135         rsurface.modelnormal3f_bufferoffset = 0;
11136         rsurface.modelgeneratedvertex = true;
11137         rsurface.modellightmapcolor4f  = color4f;
11138         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11139         rsurface.modellightmapcolor4f_bufferoffset = 0;
11140         rsurface.modeltexcoordtexture2f  = texcoord2f;
11141         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11142         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11143         rsurface.modeltexcoordlightmap2f  = NULL;
11144         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11145         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11146         rsurface.modelelement3i = element3i;
11147         rsurface.modelelement3i_indexbuffer = NULL;
11148         rsurface.modelelement3i_bufferoffset = 0;
11149         rsurface.modelelement3s = element3s;
11150         rsurface.modelelement3s_indexbuffer = NULL;
11151         rsurface.modelelement3s_bufferoffset = 0;
11152         rsurface.modellightmapoffsets = NULL;
11153         rsurface.modelsurfaces = NULL;
11154         rsurface.batchgeneratedvertex = false;
11155         rsurface.batchfirstvertex = 0;
11156         rsurface.batchnumvertices = 0;
11157         rsurface.batchfirsttriangle = 0;
11158         rsurface.batchnumtriangles = 0;
11159         rsurface.batchvertex3f  = NULL;
11160         rsurface.batchvertex3f_vertexbuffer = NULL;
11161         rsurface.batchvertex3f_bufferoffset = 0;
11162         rsurface.batchsvector3f = NULL;
11163         rsurface.batchsvector3f_vertexbuffer = NULL;
11164         rsurface.batchsvector3f_bufferoffset = 0;
11165         rsurface.batchtvector3f = NULL;
11166         rsurface.batchtvector3f_vertexbuffer = NULL;
11167         rsurface.batchtvector3f_bufferoffset = 0;
11168         rsurface.batchnormal3f  = NULL;
11169         rsurface.batchnormal3f_vertexbuffer = NULL;
11170         rsurface.batchnormal3f_bufferoffset = 0;
11171         rsurface.batchlightmapcolor4f = NULL;
11172         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11173         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11174         rsurface.batchtexcoordtexture2f = NULL;
11175         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11176         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11177         rsurface.batchtexcoordlightmap2f = NULL;
11178         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11179         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11180         rsurface.batchvertexmesh = NULL;
11181         rsurface.batchvertexmeshbuffer = NULL;
11182         rsurface.batchvertexposition = NULL;
11183         rsurface.batchvertexpositionbuffer = NULL;
11184         rsurface.batchelement3i = NULL;
11185         rsurface.batchelement3i_indexbuffer = NULL;
11186         rsurface.batchelement3i_bufferoffset = 0;
11187         rsurface.batchelement3s = NULL;
11188         rsurface.batchelement3s_indexbuffer = NULL;
11189         rsurface.batchelement3s_bufferoffset = 0;
11190         rsurface.passcolor4f = NULL;
11191         rsurface.passcolor4f_vertexbuffer = NULL;
11192         rsurface.passcolor4f_bufferoffset = 0;
11193
11194         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11195         {
11196                 if ((wantnormals || wanttangents) && !normal3f)
11197                 {
11198                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11199                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11200                 }
11201                 if (wanttangents && !svector3f)
11202                 {
11203                         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);
11204                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11205                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11206                 }
11207         }
11208
11209         // now convert arrays into vertexmesh structs
11210         for (i = 0;i < numvertices;i++)
11211         {
11212                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11213                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11214                 if (rsurface.modelsvector3f)
11215                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11216                 if (rsurface.modeltvector3f)
11217                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11218                 if (rsurface.modelnormal3f)
11219                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11220                 if (rsurface.modellightmapcolor4f)
11221                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11222                 if (rsurface.modeltexcoordtexture2f)
11223                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11224                 if (rsurface.modeltexcoordlightmap2f)
11225                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11226         }
11227 }
11228
11229 float RSurf_FogPoint(const float *v)
11230 {
11231         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11232         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11233         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11234         float FogHeightFade = r_refdef.fogheightfade;
11235         float fogfrac;
11236         unsigned int fogmasktableindex;
11237         if (r_refdef.fogplaneviewabove)
11238                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11239         else
11240                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11241         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11242         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11243 }
11244
11245 float RSurf_FogVertex(const float *v)
11246 {
11247         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11248         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11249         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11250         float FogHeightFade = rsurface.fogheightfade;
11251         float fogfrac;
11252         unsigned int fogmasktableindex;
11253         if (r_refdef.fogplaneviewabove)
11254                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11255         else
11256                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11257         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11258         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11259 }
11260
11261 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11262 {
11263         int i;
11264         for (i = 0;i < numelements;i++)
11265                 outelement3i[i] = inelement3i[i] + adjust;
11266 }
11267
11268 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11269 extern cvar_t gl_vbo;
11270 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11271 {
11272         int deformindex;
11273         int firsttriangle;
11274         int numtriangles;
11275         int firstvertex;
11276         int endvertex;
11277         int numvertices;
11278         int surfacefirsttriangle;
11279         int surfacenumtriangles;
11280         int surfacefirstvertex;
11281         int surfaceendvertex;
11282         int surfacenumvertices;
11283         int surfaceadjustvertex;
11284         int needsupdate;
11285         int i, j;
11286         qboolean gaps;
11287         qboolean dynamicvertex;
11288         float amplitude;
11289         float animpos;
11290         float scale;
11291         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11292         float waveparms[4];
11293         q3shaderinfo_deform_t *deform;
11294         const msurface_t *surface, *firstsurface;
11295         r_vertexposition_t *vertexposition;
11296         r_vertexmesh_t *vertexmesh;
11297         if (!texturenumsurfaces)
11298                 return;
11299         // find vertex range of this surface batch
11300         gaps = false;
11301         firstsurface = texturesurfacelist[0];
11302         firsttriangle = firstsurface->num_firsttriangle;
11303         numtriangles = 0;
11304         firstvertex = endvertex = firstsurface->num_firstvertex;
11305         for (i = 0;i < texturenumsurfaces;i++)
11306         {
11307                 surface = texturesurfacelist[i];
11308                 if (surface != firstsurface + i)
11309                         gaps = true;
11310                 surfacefirstvertex = surface->num_firstvertex;
11311                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11312                 surfacenumtriangles = surface->num_triangles;
11313                 if (firstvertex > surfacefirstvertex)
11314                         firstvertex = surfacefirstvertex;
11315                 if (endvertex < surfaceendvertex)
11316                         endvertex = surfaceendvertex;
11317                 numtriangles += surfacenumtriangles;
11318         }
11319         if (!numtriangles)
11320                 return;
11321
11322         // we now know the vertex range used, and if there are any gaps in it
11323         rsurface.batchfirstvertex = firstvertex;
11324         rsurface.batchnumvertices = endvertex - firstvertex;
11325         rsurface.batchfirsttriangle = firsttriangle;
11326         rsurface.batchnumtriangles = numtriangles;
11327
11328         // this variable holds flags for which properties have been updated that
11329         // may require regenerating vertexmesh or vertexposition arrays...
11330         needsupdate = 0;
11331
11332         // check if any dynamic vertex processing must occur
11333         dynamicvertex = false;
11334
11335         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11336                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11337         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11338         {
11339                 switch (deform->deform)
11340                 {
11341                 default:
11342                 case Q3DEFORM_PROJECTIONSHADOW:
11343                 case Q3DEFORM_TEXT0:
11344                 case Q3DEFORM_TEXT1:
11345                 case Q3DEFORM_TEXT2:
11346                 case Q3DEFORM_TEXT3:
11347                 case Q3DEFORM_TEXT4:
11348                 case Q3DEFORM_TEXT5:
11349                 case Q3DEFORM_TEXT6:
11350                 case Q3DEFORM_TEXT7:
11351                 case Q3DEFORM_NONE:
11352                         break;
11353                 case Q3DEFORM_AUTOSPRITE:
11354                         dynamicvertex = true;
11355                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11356                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11357                         break;
11358                 case Q3DEFORM_AUTOSPRITE2:
11359                         dynamicvertex = true;
11360                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11361                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11362                         break;
11363                 case Q3DEFORM_NORMAL:
11364                         dynamicvertex = true;
11365                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11366                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11367                         break;
11368                 case Q3DEFORM_WAVE:
11369                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11370                                 break; // if wavefunc is a nop, ignore this transform
11371                         dynamicvertex = true;
11372                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11373                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11374                         break;
11375                 case Q3DEFORM_BULGE:
11376                         dynamicvertex = true;
11377                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11378                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11379                         break;
11380                 case Q3DEFORM_MOVE:
11381                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11382                                 break; // if wavefunc is a nop, ignore this transform
11383                         dynamicvertex = true;
11384                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11385                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11386                         break;
11387                 }
11388         }
11389         switch(rsurface.texture->tcgen.tcgen)
11390         {
11391         default:
11392         case Q3TCGEN_TEXTURE:
11393                 break;
11394         case Q3TCGEN_LIGHTMAP:
11395                 dynamicvertex = true;
11396                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11397                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11398                 break;
11399         case Q3TCGEN_VECTOR:
11400                 dynamicvertex = true;
11401                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11402                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11403                 break;
11404         case Q3TCGEN_ENVIRONMENT:
11405                 dynamicvertex = true;
11406                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11407                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11408                 break;
11409         }
11410         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11411         {
11412                 dynamicvertex = true;
11413                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11414                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11415         }
11416
11417         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11418         {
11419                 dynamicvertex = true;
11420                 batchneed |= BATCHNEED_NOGAPS;
11421                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11422         }
11423
11424         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11425         {
11426                 dynamicvertex = true;
11427                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11428                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11429         }
11430
11431         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11432         {
11433                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11434                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11435                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11436                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11437                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11438                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11439                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11440         }
11441
11442         // when the model data has no vertex buffer (dynamic mesh), we need to
11443         // eliminate gaps
11444         if (!rsurface.modelvertexmeshbuffer)
11445                 batchneed |= BATCHNEED_NOGAPS;
11446
11447         // if needsupdate, we have to do a dynamic vertex batch for sure
11448         if (needsupdate & batchneed)
11449                 dynamicvertex = true;
11450
11451         // see if we need to build vertexmesh from arrays
11452         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11453                 dynamicvertex = true;
11454
11455         // see if we need to build vertexposition from arrays
11456         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11457                 dynamicvertex = true;
11458
11459         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11460         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11461                 dynamicvertex = true;
11462
11463         // if there is a chance of animated vertex colors, it's a dynamic batch
11464         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11465                 dynamicvertex = true;
11466
11467         rsurface.batchvertex3f = rsurface.modelvertex3f;
11468         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11469         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11470         rsurface.batchsvector3f = rsurface.modelsvector3f;
11471         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11472         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11473         rsurface.batchtvector3f = rsurface.modeltvector3f;
11474         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11475         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11476         rsurface.batchnormal3f = rsurface.modelnormal3f;
11477         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11478         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11479         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11480         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11481         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11482         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11483         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11484         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11485         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11486         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11487         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11488         rsurface.batchvertexposition = rsurface.modelvertexposition;
11489         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11490         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11491         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11492         rsurface.batchelement3i = rsurface.modelelement3i;
11493         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11494         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11495         rsurface.batchelement3s = rsurface.modelelement3s;
11496         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11497         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11498
11499         // if any dynamic vertex processing has to occur in software, we copy the
11500         // entire surface list together before processing to rebase the vertices
11501         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11502         //
11503         // if any gaps exist and we do not have a static vertex buffer, we have to
11504         // copy the surface list together to avoid wasting upload bandwidth on the
11505         // vertices in the gaps.
11506         //
11507         // if gaps exist and we have a static vertex buffer, we still have to
11508         // combine the index buffer ranges into one dynamic index buffer.
11509         //
11510         // in all cases we end up with data that can be drawn in one call.
11511
11512         if (!dynamicvertex)
11513         {
11514                 // static vertex data, just set pointers...
11515                 rsurface.batchgeneratedvertex = false;
11516                 // if there are gaps, we want to build a combined index buffer,
11517                 // otherwise use the original static buffer with an appropriate offset
11518                 if (gaps)
11519                 {
11520                         firsttriangle = 0;
11521                         numtriangles = 0;
11522                         for (i = 0;i < texturenumsurfaces;i++)
11523                         {
11524                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11525                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11526                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11527                                 numtriangles += surfacenumtriangles;
11528                         }
11529                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11530                         rsurface.batchelement3i_indexbuffer = NULL;
11531                         rsurface.batchelement3i_bufferoffset = 0;
11532                         rsurface.batchelement3s = NULL;
11533                         rsurface.batchelement3s_indexbuffer = NULL;
11534                         rsurface.batchelement3s_bufferoffset = 0;
11535                         if (endvertex <= 65536)
11536                         {
11537                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11538                                 for (i = 0;i < numtriangles*3;i++)
11539                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11540                         }
11541                         rsurface.batchfirsttriangle = firsttriangle;
11542                         rsurface.batchnumtriangles = numtriangles;
11543                 }
11544                 return;
11545         }
11546
11547         // something needs software processing, do it for real...
11548         // we only directly handle interleaved array data in this case...
11549         rsurface.batchgeneratedvertex = true;
11550
11551         // now copy the vertex data into a combined array and make an index array
11552         // (this is what Quake3 does all the time)
11553         //if (gaps || rsurface.batchfirstvertex)
11554         {
11555                 rsurface.batchvertexposition = NULL;
11556                 rsurface.batchvertexpositionbuffer = NULL;
11557                 rsurface.batchvertexmesh = NULL;
11558                 rsurface.batchvertexmeshbuffer = NULL;
11559                 rsurface.batchvertex3f = NULL;
11560                 rsurface.batchvertex3f_vertexbuffer = NULL;
11561                 rsurface.batchvertex3f_bufferoffset = 0;
11562                 rsurface.batchsvector3f = NULL;
11563                 rsurface.batchsvector3f_vertexbuffer = NULL;
11564                 rsurface.batchsvector3f_bufferoffset = 0;
11565                 rsurface.batchtvector3f = NULL;
11566                 rsurface.batchtvector3f_vertexbuffer = NULL;
11567                 rsurface.batchtvector3f_bufferoffset = 0;
11568                 rsurface.batchnormal3f = NULL;
11569                 rsurface.batchnormal3f_vertexbuffer = NULL;
11570                 rsurface.batchnormal3f_bufferoffset = 0;
11571                 rsurface.batchlightmapcolor4f = NULL;
11572                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11573                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11574                 rsurface.batchtexcoordtexture2f = NULL;
11575                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11576                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11577                 rsurface.batchtexcoordlightmap2f = NULL;
11578                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11579                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11580                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11581                 rsurface.batchelement3i_indexbuffer = NULL;
11582                 rsurface.batchelement3i_bufferoffset = 0;
11583                 rsurface.batchelement3s = NULL;
11584                 rsurface.batchelement3s_indexbuffer = NULL;
11585                 rsurface.batchelement3s_bufferoffset = 0;
11586                 // we'll only be setting up certain arrays as needed
11587                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11588                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11589                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11590                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11591                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11592                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11593                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11594                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11595                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11596                 {
11597                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11598                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11599                 }
11600                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11601                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11602                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11603                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11604                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11605                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11606                 numvertices = 0;
11607                 numtriangles = 0;
11608                 for (i = 0;i < texturenumsurfaces;i++)
11609                 {
11610                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11611                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11612                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11613                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11614                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11615                         // copy only the data requested
11616                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11617                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11618                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11619                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11620                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11621                         {
11622                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11623                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11624                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11625                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11626                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11627                                 {
11628                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11629                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11630                                 }
11631                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11632                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11633                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11634                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11635                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11636                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11637                         }
11638                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11639                         numvertices += surfacenumvertices;
11640                         numtriangles += surfacenumtriangles;
11641                 }
11642
11643                 // generate a 16bit index array as well if possible
11644                 // (in general, dynamic batches fit)
11645                 if (numvertices <= 65536)
11646                 {
11647                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11648                         for (i = 0;i < numtriangles*3;i++)
11649                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11650                 }
11651
11652                 // since we've copied everything, the batch now starts at 0
11653                 rsurface.batchfirstvertex = 0;
11654                 rsurface.batchnumvertices = numvertices;
11655                 rsurface.batchfirsttriangle = 0;
11656                 rsurface.batchnumtriangles = numtriangles;
11657         }
11658
11659         // q1bsp surfaces rendered in vertex color mode have to have colors
11660         // calculated based on lightstyles
11661         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11662         {
11663                 // generate color arrays for the surfaces in this list
11664                 int c[4];
11665                 int scale;
11666                 int size3;
11667                 const int *offsets;
11668                 const unsigned char *lm;
11669                 numvertices = 0;
11670                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11671                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11672                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11673                 for (i = 0;i < texturenumsurfaces;i++)
11674                 {
11675                         surface = texturesurfacelist[i];
11676                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11677                         surfacenumvertices = surface->num_vertices;
11678                         if (surface->lightmapinfo->samples)
11679                         {
11680                                 for (j = 0;j < surfacenumvertices;j++)
11681                                 {
11682                                         lm = surface->lightmapinfo->samples + offsets[j];
11683                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11684                                         VectorScale(lm, scale, c);
11685                                         if (surface->lightmapinfo->styles[1] != 255)
11686                                         {
11687                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11688                                                 lm += size3;
11689                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11690                                                 VectorMA(c, scale, lm, c);
11691                                                 if (surface->lightmapinfo->styles[2] != 255)
11692                                                 {
11693                                                         lm += size3;
11694                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11695                                                         VectorMA(c, scale, lm, c);
11696                                                         if (surface->lightmapinfo->styles[3] != 255)
11697                                                         {
11698                                                                 lm += size3;
11699                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11700                                                                 VectorMA(c, scale, lm, c);
11701                                                         }
11702                                                 }
11703                                         }
11704                                         c[0] >>= 15;
11705                                         c[1] >>= 15;
11706                                         c[2] >>= 15;
11707                                         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);
11708                                         numvertices++;
11709                                 }
11710                         }
11711                         else
11712                         {
11713                                 for (j = 0;j < surfacenumvertices;j++)
11714                                 {
11715                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11716                                         numvertices++;
11717                                 }
11718                         }
11719                 }
11720         }
11721
11722         // if vertices are deformed (sprite flares and things in maps, possibly
11723         // water waves, bulges and other deformations), modify the copied vertices
11724         // in place
11725         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11726         {
11727                 switch (deform->deform)
11728                 {
11729                 default:
11730                 case Q3DEFORM_PROJECTIONSHADOW:
11731                 case Q3DEFORM_TEXT0:
11732                 case Q3DEFORM_TEXT1:
11733                 case Q3DEFORM_TEXT2:
11734                 case Q3DEFORM_TEXT3:
11735                 case Q3DEFORM_TEXT4:
11736                 case Q3DEFORM_TEXT5:
11737                 case Q3DEFORM_TEXT6:
11738                 case Q3DEFORM_TEXT7:
11739                 case Q3DEFORM_NONE:
11740                         break;
11741                 case Q3DEFORM_AUTOSPRITE:
11742                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11743                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11744                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11745                         VectorNormalize(newforward);
11746                         VectorNormalize(newright);
11747                         VectorNormalize(newup);
11748                         // a single autosprite surface can contain multiple sprites...
11749                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11750                         {
11751                                 VectorClear(center);
11752                                 for (i = 0;i < 4;i++)
11753                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11754                                 VectorScale(center, 0.25f, center);
11755                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11756                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11757                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11758                                 for (i = 0;i < 4;i++)
11759                                 {
11760                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11761                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11762                                 }
11763                         }
11764                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11765                         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);
11766                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11767                         rsurface.batchvertex3f_vertexbuffer = NULL;
11768                         rsurface.batchvertex3f_bufferoffset = 0;
11769                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11770                         rsurface.batchsvector3f_vertexbuffer = NULL;
11771                         rsurface.batchsvector3f_bufferoffset = 0;
11772                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11773                         rsurface.batchtvector3f_vertexbuffer = NULL;
11774                         rsurface.batchtvector3f_bufferoffset = 0;
11775                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11776                         rsurface.batchnormal3f_vertexbuffer = NULL;
11777                         rsurface.batchnormal3f_bufferoffset = 0;
11778                         break;
11779                 case Q3DEFORM_AUTOSPRITE2:
11780                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11781                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11782                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11783                         VectorNormalize(newforward);
11784                         VectorNormalize(newright);
11785                         VectorNormalize(newup);
11786                         {
11787                                 const float *v1, *v2;
11788                                 vec3_t start, end;
11789                                 float f, l;
11790                                 struct
11791                                 {
11792                                         float length2;
11793                                         const float *v1;
11794                                         const float *v2;
11795                                 }
11796                                 shortest[2];
11797                                 memset(shortest, 0, sizeof(shortest));
11798                                 // a single autosprite surface can contain multiple sprites...
11799                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11800                                 {
11801                                         VectorClear(center);
11802                                         for (i = 0;i < 4;i++)
11803                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11804                                         VectorScale(center, 0.25f, center);
11805                                         // find the two shortest edges, then use them to define the
11806                                         // axis vectors for rotating around the central axis
11807                                         for (i = 0;i < 6;i++)
11808                                         {
11809                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11810                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11811                                                 l = VectorDistance2(v1, v2);
11812                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11813                                                 if (v1[2] != v2[2])
11814                                                         l += (1.0f / 1024.0f);
11815                                                 if (shortest[0].length2 > l || i == 0)
11816                                                 {
11817                                                         shortest[1] = shortest[0];
11818                                                         shortest[0].length2 = l;
11819                                                         shortest[0].v1 = v1;
11820                                                         shortest[0].v2 = v2;
11821                                                 }
11822                                                 else if (shortest[1].length2 > l || i == 1)
11823                                                 {
11824                                                         shortest[1].length2 = l;
11825                                                         shortest[1].v1 = v1;
11826                                                         shortest[1].v2 = v2;
11827                                                 }
11828                                         }
11829                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11830                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11831                                         // this calculates the right vector from the shortest edge
11832                                         // and the up vector from the edge midpoints
11833                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11834                                         VectorNormalize(right);
11835                                         VectorSubtract(end, start, up);
11836                                         VectorNormalize(up);
11837                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11838                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11839                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11840                                         VectorNegate(forward, forward);
11841                                         VectorReflect(forward, 0, up, forward);
11842                                         VectorNormalize(forward);
11843                                         CrossProduct(up, forward, newright);
11844                                         VectorNormalize(newright);
11845                                         // rotate the quad around the up axis vector, this is made
11846                                         // especially easy by the fact we know the quad is flat,
11847                                         // so we only have to subtract the center position and
11848                                         // measure distance along the right vector, and then
11849                                         // multiply that by the newright vector and add back the
11850                                         // center position
11851                                         // we also need to subtract the old position to undo the
11852                                         // displacement from the center, which we do with a
11853                                         // DotProduct, the subtraction/addition of center is also
11854                                         // optimized into DotProducts here
11855                                         l = DotProduct(right, center);
11856                                         for (i = 0;i < 4;i++)
11857                                         {
11858                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11859                                                 f = DotProduct(right, v1) - l;
11860                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11861                                         }
11862                                 }
11863                         }
11864                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11865                         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);
11866                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11867                         rsurface.batchvertex3f_vertexbuffer = NULL;
11868                         rsurface.batchvertex3f_bufferoffset = 0;
11869                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11870                         rsurface.batchsvector3f_vertexbuffer = NULL;
11871                         rsurface.batchsvector3f_bufferoffset = 0;
11872                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11873                         rsurface.batchtvector3f_vertexbuffer = NULL;
11874                         rsurface.batchtvector3f_bufferoffset = 0;
11875                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11876                         rsurface.batchnormal3f_vertexbuffer = NULL;
11877                         rsurface.batchnormal3f_bufferoffset = 0;
11878                         break;
11879                 case Q3DEFORM_NORMAL:
11880                         // deform the normals to make reflections wavey
11881                         for (j = 0;j < rsurface.batchnumvertices;j++)
11882                         {
11883                                 float vertex[3];
11884                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11885                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11886                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11887                                 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]);
11888                                 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]);
11889                                 VectorNormalize(normal);
11890                         }
11891                         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);
11892                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11893                         rsurface.batchsvector3f_vertexbuffer = NULL;
11894                         rsurface.batchsvector3f_bufferoffset = 0;
11895                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11896                         rsurface.batchtvector3f_vertexbuffer = NULL;
11897                         rsurface.batchtvector3f_bufferoffset = 0;
11898                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11899                         rsurface.batchnormal3f_vertexbuffer = NULL;
11900                         rsurface.batchnormal3f_bufferoffset = 0;
11901                         break;
11902                 case Q3DEFORM_WAVE:
11903                         // deform vertex array to make wavey water and flags and such
11904                         waveparms[0] = deform->waveparms[0];
11905                         waveparms[1] = deform->waveparms[1];
11906                         waveparms[2] = deform->waveparms[2];
11907                         waveparms[3] = deform->waveparms[3];
11908                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11909                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11910                         // this is how a divisor of vertex influence on deformation
11911                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11912                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11913                         for (j = 0;j < rsurface.batchnumvertices;j++)
11914                         {
11915                                 // if the wavefunc depends on time, evaluate it per-vertex
11916                                 if (waveparms[3])
11917                                 {
11918                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11919                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11920                                 }
11921                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11922                         }
11923                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11924                         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);
11925                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11926                         rsurface.batchvertex3f_vertexbuffer = NULL;
11927                         rsurface.batchvertex3f_bufferoffset = 0;
11928                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11929                         rsurface.batchsvector3f_vertexbuffer = NULL;
11930                         rsurface.batchsvector3f_bufferoffset = 0;
11931                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11932                         rsurface.batchtvector3f_vertexbuffer = NULL;
11933                         rsurface.batchtvector3f_bufferoffset = 0;
11934                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11935                         rsurface.batchnormal3f_vertexbuffer = NULL;
11936                         rsurface.batchnormal3f_bufferoffset = 0;
11937                         break;
11938                 case Q3DEFORM_BULGE:
11939                         // deform vertex array to make the surface have moving bulges
11940                         for (j = 0;j < rsurface.batchnumvertices;j++)
11941                         {
11942                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11943                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11944                         }
11945                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11946                         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);
11947                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11948                         rsurface.batchvertex3f_vertexbuffer = NULL;
11949                         rsurface.batchvertex3f_bufferoffset = 0;
11950                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11951                         rsurface.batchsvector3f_vertexbuffer = NULL;
11952                         rsurface.batchsvector3f_bufferoffset = 0;
11953                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11954                         rsurface.batchtvector3f_vertexbuffer = NULL;
11955                         rsurface.batchtvector3f_bufferoffset = 0;
11956                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11957                         rsurface.batchnormal3f_vertexbuffer = NULL;
11958                         rsurface.batchnormal3f_bufferoffset = 0;
11959                         break;
11960                 case Q3DEFORM_MOVE:
11961                         // deform vertex array
11962                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11963                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11964                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11965                         VectorScale(deform->parms, scale, waveparms);
11966                         for (j = 0;j < rsurface.batchnumvertices;j++)
11967                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11968                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11969                         rsurface.batchvertex3f_vertexbuffer = NULL;
11970                         rsurface.batchvertex3f_bufferoffset = 0;
11971                         break;
11972                 }
11973         }
11974
11975         // generate texcoords based on the chosen texcoord source
11976         switch(rsurface.texture->tcgen.tcgen)
11977         {
11978         default:
11979         case Q3TCGEN_TEXTURE:
11980                 break;
11981         case Q3TCGEN_LIGHTMAP:
11982                 if (rsurface.batchtexcoordlightmap2f)
11983                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11984                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11985                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11986                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11987                 break;
11988         case Q3TCGEN_VECTOR:
11989                 for (j = 0;j < rsurface.batchnumvertices;j++)
11990                 {
11991                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11992                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11993                 }
11994                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11995                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11996                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11997                 break;
11998         case Q3TCGEN_ENVIRONMENT:
11999                 // make environment reflections using a spheremap
12000                 for (j = 0;j < rsurface.batchnumvertices;j++)
12001                 {
12002                         // identical to Q3A's method, but executed in worldspace so
12003                         // carried models can be shiny too
12004
12005                         float viewer[3], d, reflected[3], worldreflected[3];
12006
12007                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12008                         // VectorNormalize(viewer);
12009
12010                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12011
12012                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12013                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12014                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12015                         // note: this is proportinal to viewer, so we can normalize later
12016
12017                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12018                         VectorNormalize(worldreflected);
12019
12020                         // note: this sphere map only uses world x and z!
12021                         // so positive and negative y will LOOK THE SAME.
12022                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12023                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12024                 }
12025                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12026                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12027                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12028                 break;
12029         }
12030         // the only tcmod that needs software vertex processing is turbulent, so
12031         // check for it here and apply the changes if needed
12032         // and we only support that as the first one
12033         // (handling a mixture of turbulent and other tcmods would be problematic
12034         //  without punting it entirely to a software path)
12035         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12036         {
12037                 amplitude = rsurface.texture->tcmods[0].parms[1];
12038                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12039                 for (j = 0;j < rsurface.batchnumvertices;j++)
12040                 {
12041                         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);
12042                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12043                 }
12044                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12045                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12046                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12047         }
12048
12049         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12050         {
12051                 // convert the modified arrays to vertex structs
12052                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12053                 rsurface.batchvertexmeshbuffer = NULL;
12054                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12055                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12056                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12057                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12058                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12059                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12060                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12061                 {
12062                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12063                         {
12064                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12065                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12066                         }
12067                 }
12068                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12069                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12070                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12071                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12072                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12073                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12074                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12075                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12076                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12077         }
12078
12079         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12080         {
12081                 // convert the modified arrays to vertex structs
12082                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12083                 rsurface.batchvertexpositionbuffer = NULL;
12084                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12085                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12086                 else
12087                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12088                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12089         }
12090 }
12091
12092 void RSurf_DrawBatch(void)
12093 {
12094         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);
12095 }
12096
12097 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12098 {
12099         // pick the closest matching water plane
12100         int planeindex, vertexindex, bestplaneindex = -1;
12101         float d, bestd;
12102         vec3_t vert;
12103         const float *v;
12104         r_waterstate_waterplane_t *p;
12105         bestd = 0;
12106         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12107         {
12108                 if(p->camera_entity != rsurface.texture->camera_entity)
12109                         continue;
12110                 d = 0;
12111                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12112                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12113                 {
12114                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12115                         d += fabs(PlaneDiff(vert, &p->plane));
12116                 }
12117                 if (bestd > d || bestplaneindex < 0)
12118                 {
12119                         bestd = d;
12120                         bestplaneindex = planeindex;
12121                 }
12122         }
12123         return bestplaneindex;
12124 }
12125
12126 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12127 {
12128         int i;
12129         for (i = 0;i < rsurface.batchnumvertices;i++)
12130                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12131         rsurface.passcolor4f = rsurface.array_passcolor4f;
12132         rsurface.passcolor4f_vertexbuffer = 0;
12133         rsurface.passcolor4f_bufferoffset = 0;
12134 }
12135
12136 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12137 {
12138         int i;
12139         float f;
12140         const float *v;
12141         const float *c;
12142         float *c2;
12143         if (rsurface.passcolor4f)
12144         {
12145                 // generate color arrays
12146                 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)
12147                 {
12148                         f = RSurf_FogVertex(v);
12149                         c2[0] = c[0] * f;
12150                         c2[1] = c[1] * f;
12151                         c2[2] = c[2] * f;
12152                         c2[3] = c[3];
12153                 }
12154         }
12155         else
12156         {
12157                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12158                 {
12159                         f = RSurf_FogVertex(v);
12160                         c2[0] = f;
12161                         c2[1] = f;
12162                         c2[2] = f;
12163                         c2[3] = 1;
12164                 }
12165         }
12166         rsurface.passcolor4f = rsurface.array_passcolor4f;
12167         rsurface.passcolor4f_vertexbuffer = 0;
12168         rsurface.passcolor4f_bufferoffset = 0;
12169 }
12170
12171 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12172 {
12173         int i;
12174         float f;
12175         const float *v;
12176         const float *c;
12177         float *c2;
12178         if (!rsurface.passcolor4f)
12179                 return;
12180         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)
12181         {
12182                 f = RSurf_FogVertex(v);
12183                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12184                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12185                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12186                 c2[3] = c[3];
12187         }
12188         rsurface.passcolor4f = rsurface.array_passcolor4f;
12189         rsurface.passcolor4f_vertexbuffer = 0;
12190         rsurface.passcolor4f_bufferoffset = 0;
12191 }
12192
12193 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12194 {
12195         int i;
12196         const float *c;
12197         float *c2;
12198         if (!rsurface.passcolor4f)
12199                 return;
12200         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12201         {
12202                 c2[0] = c[0] * r;
12203                 c2[1] = c[1] * g;
12204                 c2[2] = c[2] * b;
12205                 c2[3] = c[3] * a;
12206         }
12207         rsurface.passcolor4f = rsurface.array_passcolor4f;
12208         rsurface.passcolor4f_vertexbuffer = 0;
12209         rsurface.passcolor4f_bufferoffset = 0;
12210 }
12211
12212 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12213 {
12214         int i;
12215         const float *c;
12216         float *c2;
12217         if (!rsurface.passcolor4f)
12218                 return;
12219         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12220         {
12221                 c2[0] = c[0] + r_refdef.scene.ambient;
12222                 c2[1] = c[1] + r_refdef.scene.ambient;
12223                 c2[2] = c[2] + r_refdef.scene.ambient;
12224                 c2[3] = c[3];
12225         }
12226         rsurface.passcolor4f = rsurface.array_passcolor4f;
12227         rsurface.passcolor4f_vertexbuffer = 0;
12228         rsurface.passcolor4f_bufferoffset = 0;
12229 }
12230
12231 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12232 {
12233         // TODO: optimize
12234         rsurface.passcolor4f = NULL;
12235         rsurface.passcolor4f_vertexbuffer = 0;
12236         rsurface.passcolor4f_bufferoffset = 0;
12237         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12238         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12239         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12240         GL_Color(r, g, b, a);
12241         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12242         RSurf_DrawBatch();
12243 }
12244
12245 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12246 {
12247         // TODO: optimize applyfog && applycolor case
12248         // just apply fog if necessary, and tint the fog color array if necessary
12249         rsurface.passcolor4f = NULL;
12250         rsurface.passcolor4f_vertexbuffer = 0;
12251         rsurface.passcolor4f_bufferoffset = 0;
12252         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12253         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12254         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12255         GL_Color(r, g, b, a);
12256         RSurf_DrawBatch();
12257 }
12258
12259 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12260 {
12261         // TODO: optimize
12262         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12263         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12264         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12265         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12266         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12267         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12268         GL_Color(r, g, b, a);
12269         RSurf_DrawBatch();
12270 }
12271
12272 static void RSurf_DrawBatch_GL11_ClampColor(void)
12273 {
12274         int i;
12275         const float *c1;
12276         float *c2;
12277         if (!rsurface.passcolor4f)
12278                 return;
12279         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12280         {
12281                 c2[0] = bound(0.0f, c1[0], 1.0f);
12282                 c2[1] = bound(0.0f, c1[1], 1.0f);
12283                 c2[2] = bound(0.0f, c1[2], 1.0f);
12284                 c2[3] = bound(0.0f, c1[3], 1.0f);
12285         }
12286 }
12287
12288 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12289 {
12290         int i;
12291         float f;
12292         float alpha;
12293         const float *v;
12294         const float *n;
12295         float *c;
12296         vec3_t ambientcolor;
12297         vec3_t diffusecolor;
12298         vec3_t lightdir;
12299         // TODO: optimize
12300         // model lighting
12301         VectorCopy(rsurface.modellight_lightdir, lightdir);
12302         f = 0.5f * r_refdef.lightmapintensity;
12303         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12304         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12305         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12306         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12307         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12308         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12309         alpha = *a;
12310         if (VectorLength2(diffusecolor) > 0)
12311         {
12312                 // q3-style directional shading
12313                 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)
12314                 {
12315                         if ((f = DotProduct(n, lightdir)) > 0)
12316                                 VectorMA(ambientcolor, f, diffusecolor, c);
12317                         else
12318                                 VectorCopy(ambientcolor, c);
12319                         c[3] = alpha;
12320                 }
12321                 *r = 1;
12322                 *g = 1;
12323                 *b = 1;
12324                 *a = 1;
12325                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12326                 rsurface.passcolor4f_vertexbuffer = 0;
12327                 rsurface.passcolor4f_bufferoffset = 0;
12328                 *applycolor = false;
12329         }
12330         else
12331         {
12332                 *r = ambientcolor[0];
12333                 *g = ambientcolor[1];
12334                 *b = ambientcolor[2];
12335                 rsurface.passcolor4f = NULL;
12336                 rsurface.passcolor4f_vertexbuffer = 0;
12337                 rsurface.passcolor4f_bufferoffset = 0;
12338         }
12339 }
12340
12341 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12342 {
12343         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12344         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12345         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12346         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12347         GL_Color(r, g, b, a);
12348         RSurf_DrawBatch();
12349 }
12350
12351 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12352 {
12353         int i;
12354         float f;
12355         const float *v;
12356         float *c;
12357         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12358         {
12359                 f = 1 - RSurf_FogVertex(v);
12360                 c[0] = r;
12361                 c[1] = g;
12362                 c[2] = b;
12363                 c[3] = f * a;
12364         }
12365 }
12366
12367 void RSurf_SetupDepthAndCulling(void)
12368 {
12369         // submodels are biased to avoid z-fighting with world surfaces that they
12370         // may be exactly overlapping (avoids z-fighting artifacts on certain
12371         // doors and things in Quake maps)
12372         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12373         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12374         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12375         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12376 }
12377
12378 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12379 {
12380         // transparent sky would be ridiculous
12381         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12382                 return;
12383         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12384         skyrenderlater = true;
12385         RSurf_SetupDepthAndCulling();
12386         GL_DepthMask(true);
12387         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12388         // skymasking on them, and Quake3 never did sky masking (unlike
12389         // software Quake and software Quake2), so disable the sky masking
12390         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12391         // and skymasking also looks very bad when noclipping outside the
12392         // level, so don't use it then either.
12393         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12394         {
12395                 R_Mesh_ResetTextureState();
12396                 if (skyrendermasked)
12397                 {
12398                         R_SetupShader_DepthOrShadow();
12399                         // depth-only (masking)
12400                         GL_ColorMask(0,0,0,0);
12401                         // just to make sure that braindead drivers don't draw
12402                         // anything despite that colormask...
12403                         GL_BlendFunc(GL_ZERO, GL_ONE);
12404                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12405                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12406                 }
12407                 else
12408                 {
12409                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12410                         // fog sky
12411                         GL_BlendFunc(GL_ONE, GL_ZERO);
12412                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12413                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12414                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12415                 }
12416                 RSurf_DrawBatch();
12417                 if (skyrendermasked)
12418                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12419         }
12420         R_Mesh_ResetTextureState();
12421         GL_Color(1, 1, 1, 1);
12422 }
12423
12424 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12425 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12426 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12427 {
12428         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12429                 return;
12430         if (prepass)
12431         {
12432                 // render screenspace normalmap to texture
12433                 GL_DepthMask(true);
12434                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12435                 RSurf_DrawBatch();
12436                 return;
12437         }
12438
12439         // bind lightmap texture
12440
12441         // water/refraction/reflection/camera surfaces have to be handled specially
12442         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12443         {
12444                 int start, end, startplaneindex;
12445                 for (start = 0;start < texturenumsurfaces;start = end)
12446                 {
12447                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12448                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12449                                 ;
12450                         // now that we have a batch using the same planeindex, render it
12451                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12452                         {
12453                                 // render water or distortion background
12454                                 GL_DepthMask(true);
12455                                 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));
12456                                 RSurf_DrawBatch();
12457                                 // blend surface on top
12458                                 GL_DepthMask(false);
12459                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12460                                 RSurf_DrawBatch();
12461                         }
12462                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12463                         {
12464                                 // render surface with reflection texture as input
12465                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12466                                 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));
12467                                 RSurf_DrawBatch();
12468                         }
12469                 }
12470                 return;
12471         }
12472
12473         // render surface batch normally
12474         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12475         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12476         RSurf_DrawBatch();
12477 }
12478
12479 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12480 {
12481         // OpenGL 1.3 path - anything not completely ancient
12482         qboolean applycolor;
12483         qboolean applyfog;
12484         int layerindex;
12485         const texturelayer_t *layer;
12486         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);
12487         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12488
12489         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12490         {
12491                 vec4_t layercolor;
12492                 int layertexrgbscale;
12493                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12494                 {
12495                         if (layerindex == 0)
12496                                 GL_AlphaTest(true);
12497                         else
12498                         {
12499                                 GL_AlphaTest(false);
12500                                 GL_DepthFunc(GL_EQUAL);
12501                         }
12502                 }
12503                 GL_DepthMask(layer->depthmask && writedepth);
12504                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12505                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12506                 {
12507                         layertexrgbscale = 4;
12508                         VectorScale(layer->color, 0.25f, layercolor);
12509                 }
12510                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12511                 {
12512                         layertexrgbscale = 2;
12513                         VectorScale(layer->color, 0.5f, layercolor);
12514                 }
12515                 else
12516                 {
12517                         layertexrgbscale = 1;
12518                         VectorScale(layer->color, 1.0f, layercolor);
12519                 }
12520                 layercolor[3] = layer->color[3];
12521                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12522                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12523                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12524                 switch (layer->type)
12525                 {
12526                 case TEXTURELAYERTYPE_LITTEXTURE:
12527                         // single-pass lightmapped texture with 2x rgbscale
12528                         R_Mesh_TexBind(0, r_texture_white);
12529                         R_Mesh_TexMatrix(0, NULL);
12530                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12531                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12532                         R_Mesh_TexBind(1, layer->texture);
12533                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12534                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12535                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12536                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12537                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12538                         else if (rsurface.uselightmaptexture)
12539                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12540                         else
12541                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12542                         break;
12543                 case TEXTURELAYERTYPE_TEXTURE:
12544                         // singletexture unlit texture with transparency support
12545                         R_Mesh_TexBind(0, layer->texture);
12546                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12547                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12548                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12549                         R_Mesh_TexBind(1, 0);
12550                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12551                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12552                         break;
12553                 case TEXTURELAYERTYPE_FOG:
12554                         // singletexture fogging
12555                         if (layer->texture)
12556                         {
12557                                 R_Mesh_TexBind(0, layer->texture);
12558                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12559                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12560                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12561                         }
12562                         else
12563                         {
12564                                 R_Mesh_TexBind(0, 0);
12565                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12566                         }
12567                         R_Mesh_TexBind(1, 0);
12568                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12569                         // generate a color array for the fog pass
12570                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12571                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12572                         RSurf_DrawBatch();
12573                         break;
12574                 default:
12575                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12576                 }
12577         }
12578         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12579         {
12580                 GL_DepthFunc(GL_LEQUAL);
12581                 GL_AlphaTest(false);
12582         }
12583 }
12584
12585 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12586 {
12587         // OpenGL 1.1 - crusty old voodoo path
12588         qboolean applyfog;
12589         int layerindex;
12590         const texturelayer_t *layer;
12591         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);
12592         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12593
12594         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12595         {
12596                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12597                 {
12598                         if (layerindex == 0)
12599                                 GL_AlphaTest(true);
12600                         else
12601                         {
12602                                 GL_AlphaTest(false);
12603                                 GL_DepthFunc(GL_EQUAL);
12604                         }
12605                 }
12606                 GL_DepthMask(layer->depthmask && writedepth);
12607                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12608                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12609                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12610                 switch (layer->type)
12611                 {
12612                 case TEXTURELAYERTYPE_LITTEXTURE:
12613                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12614                         {
12615                                 // two-pass lit texture with 2x rgbscale
12616                                 // first the lightmap pass
12617                                 R_Mesh_TexBind(0, r_texture_white);
12618                                 R_Mesh_TexMatrix(0, NULL);
12619                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12620                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12621                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12622                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12623                                 else if (rsurface.uselightmaptexture)
12624                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12625                                 else
12626                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12627                                 // then apply the texture to it
12628                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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                                 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);
12634                         }
12635                         else
12636                         {
12637                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12638                                 R_Mesh_TexBind(0, layer->texture);
12639                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12640                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12641                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12642                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12643                                         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);
12644                                 else
12645                                         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);
12646                         }
12647                         break;
12648                 case TEXTURELAYERTYPE_TEXTURE:
12649                         // singletexture unlit texture with transparency support
12650                         R_Mesh_TexBind(0, layer->texture);
12651                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12652                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12653                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12654                         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);
12655                         break;
12656                 case TEXTURELAYERTYPE_FOG:
12657                         // singletexture fogging
12658                         if (layer->texture)
12659                         {
12660                                 R_Mesh_TexBind(0, layer->texture);
12661                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12662                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12663                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12664                         }
12665                         else
12666                         {
12667                                 R_Mesh_TexBind(0, 0);
12668                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12669                         }
12670                         // generate a color array for the fog pass
12671                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12672                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12673                         RSurf_DrawBatch();
12674                         break;
12675                 default:
12676                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12677                 }
12678         }
12679         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12680         {
12681                 GL_DepthFunc(GL_LEQUAL);
12682                 GL_AlphaTest(false);
12683         }
12684 }
12685
12686 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12687 {
12688         int vi;
12689         int j;
12690         r_vertexgeneric_t *batchvertex;
12691         float c[4];
12692
12693         GL_AlphaTest(false);
12694         R_Mesh_ResetTextureState();
12695         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12696
12697         if(rsurface.texture && rsurface.texture->currentskinframe)
12698         {
12699                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12700                 c[3] *= rsurface.texture->currentalpha;
12701         }
12702         else
12703         {
12704                 c[0] = 1;
12705                 c[1] = 0;
12706                 c[2] = 1;
12707                 c[3] = 1;
12708         }
12709
12710         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12711         {
12712                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12713                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12714                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12715         }
12716
12717         // brighten it up (as texture value 127 means "unlit")
12718         c[0] *= 2 * r_refdef.view.colorscale;
12719         c[1] *= 2 * r_refdef.view.colorscale;
12720         c[2] *= 2 * r_refdef.view.colorscale;
12721
12722         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12723                 c[3] *= r_wateralpha.value;
12724
12725         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12726         {
12727                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12728                 GL_DepthMask(false);
12729         }
12730         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12731         {
12732                 GL_BlendFunc(GL_ONE, GL_ONE);
12733                 GL_DepthMask(false);
12734         }
12735         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12736         {
12737                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12738                 GL_DepthMask(false);
12739         }
12740         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12741         {
12742                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12743                 GL_DepthMask(false);
12744         }
12745         else
12746         {
12747                 GL_BlendFunc(GL_ONE, GL_ZERO);
12748                 GL_DepthMask(writedepth);
12749         }
12750
12751         if (r_showsurfaces.integer == 3)
12752         {
12753                 rsurface.passcolor4f = NULL;
12754
12755                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12756                 {
12757                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12758
12759                         rsurface.passcolor4f = NULL;
12760                         rsurface.passcolor4f_vertexbuffer = 0;
12761                         rsurface.passcolor4f_bufferoffset = 0;
12762                 }
12763                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12764                 {
12765                         qboolean applycolor = true;
12766                         float one = 1.0;
12767
12768                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12769
12770                         r_refdef.lightmapintensity = 1;
12771                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12772                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12773                 }
12774                 else
12775                 {
12776                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12777
12778                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12779                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12780                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12781                 }
12782
12783                 if(!rsurface.passcolor4f)
12784                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12785
12786                 RSurf_DrawBatch_GL11_ApplyAmbient();
12787                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12788                 if(r_refdef.fogenabled)
12789                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12790                 RSurf_DrawBatch_GL11_ClampColor();
12791
12792                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12793                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12794                 RSurf_DrawBatch();
12795         }
12796         else if (!r_refdef.view.showdebug)
12797         {
12798                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12799                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12800                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12801                 {
12802                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12803                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12804                 }
12805                 R_Mesh_PrepareVertices_Generic_Unlock();
12806                 RSurf_DrawBatch();
12807         }
12808         else if (r_showsurfaces.integer == 4)
12809         {
12810                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12811                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12812                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12813                 {
12814                         unsigned char c = vi << 3;
12815                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12816                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12817                 }
12818                 R_Mesh_PrepareVertices_Generic_Unlock();
12819                 RSurf_DrawBatch();
12820         }
12821         else if (r_showsurfaces.integer == 2)
12822         {
12823                 const int *e;
12824                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12825                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12826                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12827                 {
12828                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12829                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12830                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12831                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12832                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12833                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12834                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12835                 }
12836                 R_Mesh_PrepareVertices_Generic_Unlock();
12837                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12838         }
12839         else
12840         {
12841                 int texturesurfaceindex;
12842                 int k;
12843                 const msurface_t *surface;
12844                 unsigned char surfacecolor4ub[4];
12845                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12846                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12847                 vi = 0;
12848                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12849                 {
12850                         surface = texturesurfacelist[texturesurfaceindex];
12851                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12852                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12853                         for (j = 0;j < surface->num_vertices;j++)
12854                         {
12855                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12856                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12857                                 vi++;
12858                         }
12859                 }
12860                 R_Mesh_PrepareVertices_Generic_Unlock();
12861                 RSurf_DrawBatch();
12862         }
12863 }
12864
12865 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12866 {
12867         CHECKGLERROR
12868         RSurf_SetupDepthAndCulling();
12869         if (r_showsurfaces.integer)
12870         {
12871                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12872                 return;
12873         }
12874         switch (vid.renderpath)
12875         {
12876         case RENDERPATH_GL20:
12877         case RENDERPATH_CGGL:
12878         case RENDERPATH_D3D9:
12879         case RENDERPATH_D3D10:
12880         case RENDERPATH_D3D11:
12881                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12882                 break;
12883         case RENDERPATH_GL13:
12884                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12885                 break;
12886         case RENDERPATH_GL11:
12887                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12888                 break;
12889         }
12890         CHECKGLERROR
12891 }
12892
12893 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12894 {
12895         CHECKGLERROR
12896         RSurf_SetupDepthAndCulling();
12897         if (r_showsurfaces.integer)
12898         {
12899                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12900                 return;
12901         }
12902         switch (vid.renderpath)
12903         {
12904         case RENDERPATH_GL20:
12905         case RENDERPATH_CGGL:
12906         case RENDERPATH_D3D9:
12907         case RENDERPATH_D3D10:
12908         case RENDERPATH_D3D11:
12909                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12910                 break;
12911         case RENDERPATH_GL13:
12912                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12913                 break;
12914         case RENDERPATH_GL11:
12915                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12916                 break;
12917         }
12918         CHECKGLERROR
12919 }
12920
12921 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12922 {
12923         int i, j;
12924         int texturenumsurfaces, endsurface;
12925         texture_t *texture;
12926         const msurface_t *surface;
12927 #define MAXBATCH_TRANSPARENTSURFACES 256
12928         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12929
12930         // if the model is static it doesn't matter what value we give for
12931         // wantnormals and wanttangents, so this logic uses only rules applicable
12932         // to a model, knowing that they are meaningless otherwise
12933         if (ent == r_refdef.scene.worldentity)
12934                 RSurf_ActiveWorldEntity();
12935         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12936                 RSurf_ActiveModelEntity(ent, false, false, false);
12937         else
12938         {
12939                 switch (vid.renderpath)
12940                 {
12941                 case RENDERPATH_GL20:
12942                 case RENDERPATH_CGGL:
12943                 case RENDERPATH_D3D9:
12944                 case RENDERPATH_D3D10:
12945                 case RENDERPATH_D3D11:
12946                         RSurf_ActiveModelEntity(ent, true, true, false);
12947                         break;
12948                 case RENDERPATH_GL13:
12949                 case RENDERPATH_GL11:
12950                         RSurf_ActiveModelEntity(ent, true, false, false);
12951                         break;
12952                 }
12953         }
12954
12955         if (r_transparentdepthmasking.integer)
12956         {
12957                 qboolean setup = false;
12958                 for (i = 0;i < numsurfaces;i = j)
12959                 {
12960                         j = i + 1;
12961                         surface = rsurface.modelsurfaces + surfacelist[i];
12962                         texture = surface->texture;
12963                         rsurface.texture = R_GetCurrentTexture(texture);
12964                         rsurface.lightmaptexture = NULL;
12965                         rsurface.deluxemaptexture = NULL;
12966                         rsurface.uselightmaptexture = false;
12967                         // scan ahead until we find a different texture
12968                         endsurface = min(i + 1024, numsurfaces);
12969                         texturenumsurfaces = 0;
12970                         texturesurfacelist[texturenumsurfaces++] = surface;
12971                         for (;j < endsurface;j++)
12972                         {
12973                                 surface = rsurface.modelsurfaces + surfacelist[j];
12974                                 if (texture != surface->texture)
12975                                         break;
12976                                 texturesurfacelist[texturenumsurfaces++] = surface;
12977                         }
12978                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12979                                 continue;
12980                         // render the range of surfaces as depth
12981                         if (!setup)
12982                         {
12983                                 setup = true;
12984                                 GL_ColorMask(0,0,0,0);
12985                                 GL_Color(1,1,1,1);
12986                                 GL_DepthTest(true);
12987                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12988                                 GL_DepthMask(true);
12989                                 GL_AlphaTest(false);
12990                                 R_Mesh_ResetTextureState();
12991                                 R_SetupShader_DepthOrShadow();
12992                         }
12993                         RSurf_SetupDepthAndCulling();
12994                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12995                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12996                         RSurf_DrawBatch();
12997                 }
12998                 if (setup)
12999                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13000         }
13001
13002         for (i = 0;i < numsurfaces;i = j)
13003         {
13004                 j = i + 1;
13005                 surface = rsurface.modelsurfaces + surfacelist[i];
13006                 texture = surface->texture;
13007                 rsurface.texture = R_GetCurrentTexture(texture);
13008                 rsurface.lightmaptexture = surface->lightmaptexture;
13009                 rsurface.deluxemaptexture = surface->deluxemaptexture;
13010                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13011                 // scan ahead until we find a different texture
13012                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13013                 texturenumsurfaces = 0;
13014                 texturesurfacelist[texturenumsurfaces++] = surface;
13015                 for (;j < endsurface;j++)
13016                 {
13017                         surface = rsurface.modelsurfaces + surfacelist[j];
13018                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13019                                 break;
13020                         texturesurfacelist[texturenumsurfaces++] = surface;
13021                 }
13022                 // render the range of surfaces
13023                 if (ent == r_refdef.scene.worldentity)
13024                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13025                 else
13026                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13027         }
13028         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13029         GL_AlphaTest(false);
13030 }
13031
13032 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13033 {
13034         // transparent surfaces get pushed off into the transparent queue
13035         int surfacelistindex;
13036         const msurface_t *surface;
13037         vec3_t tempcenter, center;
13038         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13039         {
13040                 surface = texturesurfacelist[surfacelistindex];
13041                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13042                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13043                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13044                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13045                 if (queueentity->transparent_offset) // transparent offset
13046                 {
13047                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13048                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13049                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13050                 }
13051                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13052         }
13053 }
13054
13055 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13056 {
13057         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13058                 return;
13059         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13060                 return;
13061         RSurf_SetupDepthAndCulling();
13062         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13063         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13064         RSurf_DrawBatch();
13065 }
13066
13067 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13068 {
13069         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13070         CHECKGLERROR
13071         if (depthonly)
13072                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13073         else if (prepass)
13074         {
13075                 if (!rsurface.texture->currentnumlayers)
13076                         return;
13077                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13078                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13079                 else
13080                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13081         }
13082         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13083                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13084         else if (!rsurface.texture->currentnumlayers)
13085                 return;
13086         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13087         {
13088                 // in the deferred case, transparent surfaces were queued during prepass
13089                 if (!r_shadow_usingdeferredprepass)
13090                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13091         }
13092         else
13093         {
13094                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13095                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13096         }
13097         CHECKGLERROR
13098 }
13099
13100 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13101 {
13102         int i, j;
13103         texture_t *texture;
13104         // break the surface list down into batches by texture and use of lightmapping
13105         for (i = 0;i < numsurfaces;i = j)
13106         {
13107                 j = i + 1;
13108                 // texture is the base texture pointer, rsurface.texture is the
13109                 // current frame/skin the texture is directing us to use (for example
13110                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13111                 // use skin 1 instead)
13112                 texture = surfacelist[i]->texture;
13113                 rsurface.texture = R_GetCurrentTexture(texture);
13114                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13115                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13116                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13117                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13118                 {
13119                         // if this texture is not the kind we want, skip ahead to the next one
13120                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13121                                 ;
13122                         continue;
13123                 }
13124                 // simply scan ahead until we find a different texture or lightmap state
13125                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13126                         ;
13127                 // render the range of surfaces
13128                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13129         }
13130 }
13131
13132 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13133 {
13134         CHECKGLERROR
13135         if (depthonly)
13136                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13137         else if (prepass)
13138         {
13139                 if (!rsurface.texture->currentnumlayers)
13140                         return;
13141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13142                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13143                 else
13144                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13145         }
13146         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13147                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13148         else if (!rsurface.texture->currentnumlayers)
13149                 return;
13150         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13151         {
13152                 // in the deferred case, transparent surfaces were queued during prepass
13153                 if (!r_shadow_usingdeferredprepass)
13154                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13155         }
13156         else
13157         {
13158                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13159                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13160         }
13161         CHECKGLERROR
13162 }
13163
13164 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13165 {
13166         int i, j;
13167         texture_t *texture;
13168         // break the surface list down into batches by texture and use of lightmapping
13169         for (i = 0;i < numsurfaces;i = j)
13170         {
13171                 j = i + 1;
13172                 // texture is the base texture pointer, rsurface.texture is the
13173                 // current frame/skin the texture is directing us to use (for example
13174                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13175                 // use skin 1 instead)
13176                 texture = surfacelist[i]->texture;
13177                 rsurface.texture = R_GetCurrentTexture(texture);
13178                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13179                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13180                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13181                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13182                 {
13183                         // if this texture is not the kind we want, skip ahead to the next one
13184                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13185                                 ;
13186                         continue;
13187                 }
13188                 // simply scan ahead until we find a different texture or lightmap state
13189                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13190                         ;
13191                 // render the range of surfaces
13192                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13193         }
13194 }
13195
13196 float locboxvertex3f[6*4*3] =
13197 {
13198         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13199         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13200         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13201         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13202         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13203         1,0,0, 0,0,0, 0,1,0, 1,1,0
13204 };
13205
13206 unsigned short locboxelements[6*2*3] =
13207 {
13208          0, 1, 2, 0, 2, 3,
13209          4, 5, 6, 4, 6, 7,
13210          8, 9,10, 8,10,11,
13211         12,13,14, 12,14,15,
13212         16,17,18, 16,18,19,
13213         20,21,22, 20,22,23
13214 };
13215
13216 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13217 {
13218         int i, j;
13219         cl_locnode_t *loc = (cl_locnode_t *)ent;
13220         vec3_t mins, size;
13221         float vertex3f[6*4*3];
13222         CHECKGLERROR
13223         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13224         GL_DepthMask(false);
13225         GL_DepthRange(0, 1);
13226         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13227         GL_DepthTest(true);
13228         GL_CullFace(GL_NONE);
13229         R_EntityMatrix(&identitymatrix);
13230
13231         R_Mesh_ResetTextureState();
13232
13233         i = surfacelist[0];
13234         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13235                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13236                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13237                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13238
13239         if (VectorCompare(loc->mins, loc->maxs))
13240         {
13241                 VectorSet(size, 2, 2, 2);
13242                 VectorMA(loc->mins, -0.5f, size, mins);
13243         }
13244         else
13245         {
13246                 VectorCopy(loc->mins, mins);
13247                 VectorSubtract(loc->maxs, loc->mins, size);
13248         }
13249
13250         for (i = 0;i < 6*4*3;)
13251                 for (j = 0;j < 3;j++, i++)
13252                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13253
13254         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13255         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13256         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13257 }
13258
13259 void R_DrawLocs(void)
13260 {
13261         int index;
13262         cl_locnode_t *loc, *nearestloc;
13263         vec3_t center;
13264         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13265         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13266         {
13267                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13268                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13269         }
13270 }
13271
13272 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13273 {
13274         if (decalsystem->decals)
13275                 Mem_Free(decalsystem->decals);
13276         memset(decalsystem, 0, sizeof(*decalsystem));
13277 }
13278
13279 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)
13280 {
13281         tridecal_t *decal;
13282         tridecal_t *decals;
13283         int i;
13284
13285         // expand or initialize the system
13286         if (decalsystem->maxdecals <= decalsystem->numdecals)
13287         {
13288                 decalsystem_t old = *decalsystem;
13289                 qboolean useshortelements;
13290                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13291                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13292                 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)));
13293                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13294                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13295                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13296                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13297                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13298                 if (decalsystem->numdecals)
13299                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13300                 if (old.decals)
13301                         Mem_Free(old.decals);
13302                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13303                         decalsystem->element3i[i] = i;
13304                 if (useshortelements)
13305                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13306                                 decalsystem->element3s[i] = i;
13307         }
13308
13309         // grab a decal and search for another free slot for the next one
13310         decals = decalsystem->decals;
13311         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13312         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13313                 ;
13314         decalsystem->freedecal = i;
13315         if (decalsystem->numdecals <= i)
13316                 decalsystem->numdecals = i + 1;
13317
13318         // initialize the decal
13319         decal->lived = 0;
13320         decal->triangleindex = triangleindex;
13321         decal->surfaceindex = surfaceindex;
13322         decal->decalsequence = decalsequence;
13323         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13324         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13325         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13326         decal->color4ub[0][3] = 255;
13327         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13328         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13329         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13330         decal->color4ub[1][3] = 255;
13331         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13332         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13333         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13334         decal->color4ub[2][3] = 255;
13335         decal->vertex3f[0][0] = v0[0];
13336         decal->vertex3f[0][1] = v0[1];
13337         decal->vertex3f[0][2] = v0[2];
13338         decal->vertex3f[1][0] = v1[0];
13339         decal->vertex3f[1][1] = v1[1];
13340         decal->vertex3f[1][2] = v1[2];
13341         decal->vertex3f[2][0] = v2[0];
13342         decal->vertex3f[2][1] = v2[1];
13343         decal->vertex3f[2][2] = v2[2];
13344         decal->texcoord2f[0][0] = t0[0];
13345         decal->texcoord2f[0][1] = t0[1];
13346         decal->texcoord2f[1][0] = t1[0];
13347         decal->texcoord2f[1][1] = t1[1];
13348         decal->texcoord2f[2][0] = t2[0];
13349         decal->texcoord2f[2][1] = t2[1];
13350 }
13351
13352 extern cvar_t cl_decals_bias;
13353 extern cvar_t cl_decals_models;
13354 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13355 // baseparms, parms, temps
13356 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)
13357 {
13358         int cornerindex;
13359         int index;
13360         float v[9][3];
13361         const float *vertex3f;
13362         int numpoints;
13363         float points[2][9][3];
13364         float temp[3];
13365         float tc[9][2];
13366         float f;
13367         float c[9][4];
13368         const int *e;
13369
13370         e = rsurface.modelelement3i + 3*triangleindex;
13371
13372         vertex3f = rsurface.modelvertex3f;
13373
13374         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13375         {
13376                 index = 3*e[cornerindex];
13377                 VectorCopy(vertex3f + index, v[cornerindex]);
13378         }
13379         // cull backfaces
13380         //TriangleNormal(v[0], v[1], v[2], normal);
13381         //if (DotProduct(normal, localnormal) < 0.0f)
13382         //      continue;
13383         // clip by each of the box planes formed from the projection matrix
13384         // if anything survives, we emit the decal
13385         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]);
13386         if (numpoints < 3)
13387                 return;
13388         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]);
13389         if (numpoints < 3)
13390                 return;
13391         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]);
13392         if (numpoints < 3)
13393                 return;
13394         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]);
13395         if (numpoints < 3)
13396                 return;
13397         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]);
13398         if (numpoints < 3)
13399                 return;
13400         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]);
13401         if (numpoints < 3)
13402                 return;
13403         // some part of the triangle survived, so we have to accept it...
13404         if (dynamic)
13405         {
13406                 // dynamic always uses the original triangle
13407                 numpoints = 3;
13408                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13409                 {
13410                         index = 3*e[cornerindex];
13411                         VectorCopy(vertex3f + index, v[cornerindex]);
13412                 }
13413         }
13414         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13415         {
13416                 // convert vertex positions to texcoords
13417                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13418                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13419                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13420                 // calculate distance fade from the projection origin
13421                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13422                 f = bound(0.0f, f, 1.0f);
13423                 c[cornerindex][0] = r * f;
13424                 c[cornerindex][1] = g * f;
13425                 c[cornerindex][2] = b * f;
13426                 c[cornerindex][3] = 1.0f;
13427                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13428         }
13429         if (dynamic)
13430                 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);
13431         else
13432                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13433                         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);
13434 }
13435 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)
13436 {
13437         matrix4x4_t projection;
13438         decalsystem_t *decalsystem;
13439         qboolean dynamic;
13440         dp_model_t *model;
13441         const msurface_t *surface;
13442         const msurface_t *surfaces;
13443         const int *surfacelist;
13444         const texture_t *texture;
13445         int numtriangles;
13446         int numsurfacelist;
13447         int surfacelistindex;
13448         int surfaceindex;
13449         int triangleindex;
13450         float localorigin[3];
13451         float localnormal[3];
13452         float localmins[3];
13453         float localmaxs[3];
13454         float localsize;
13455         //float normal[3];
13456         float planes[6][4];
13457         float angles[3];
13458         bih_t *bih;
13459         int bih_triangles_count;
13460         int bih_triangles[256];
13461         int bih_surfaces[256];
13462
13463         decalsystem = &ent->decalsystem;
13464         model = ent->model;
13465         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13466         {
13467                 R_DecalSystem_Reset(&ent->decalsystem);
13468                 return;
13469         }
13470
13471         if (!model->brush.data_leafs && !cl_decals_models.integer)
13472         {
13473                 if (decalsystem->model)
13474                         R_DecalSystem_Reset(decalsystem);
13475                 return;
13476         }
13477
13478         if (decalsystem->model != model)
13479                 R_DecalSystem_Reset(decalsystem);
13480         decalsystem->model = model;
13481
13482         RSurf_ActiveModelEntity(ent, false, false, false);
13483
13484         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13485         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13486         VectorNormalize(localnormal);
13487         localsize = worldsize*rsurface.inversematrixscale;
13488         localmins[0] = localorigin[0] - localsize;
13489         localmins[1] = localorigin[1] - localsize;
13490         localmins[2] = localorigin[2] - localsize;
13491         localmaxs[0] = localorigin[0] + localsize;
13492         localmaxs[1] = localorigin[1] + localsize;
13493         localmaxs[2] = localorigin[2] + localsize;
13494
13495         //VectorCopy(localnormal, planes[4]);
13496         //VectorVectors(planes[4], planes[2], planes[0]);
13497         AnglesFromVectors(angles, localnormal, NULL, false);
13498         AngleVectors(angles, planes[0], planes[2], planes[4]);
13499         VectorNegate(planes[0], planes[1]);
13500         VectorNegate(planes[2], planes[3]);
13501         VectorNegate(planes[4], planes[5]);
13502         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13503         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13504         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13505         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13506         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13507         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13508
13509 #if 1
13510 // works
13511 {
13512         matrix4x4_t forwardprojection;
13513         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13514         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13515 }
13516 #else
13517 // broken
13518 {
13519         float projectionvector[4][3];
13520         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13521         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13522         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13523         projectionvector[0][0] = planes[0][0] * ilocalsize;
13524         projectionvector[0][1] = planes[1][0] * ilocalsize;
13525         projectionvector[0][2] = planes[2][0] * ilocalsize;
13526         projectionvector[1][0] = planes[0][1] * ilocalsize;
13527         projectionvector[1][1] = planes[1][1] * ilocalsize;
13528         projectionvector[1][2] = planes[2][1] * ilocalsize;
13529         projectionvector[2][0] = planes[0][2] * ilocalsize;
13530         projectionvector[2][1] = planes[1][2] * ilocalsize;
13531         projectionvector[2][2] = planes[2][2] * ilocalsize;
13532         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13533         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13534         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13535         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13536 }
13537 #endif
13538
13539         dynamic = model->surfmesh.isanimated;
13540         numsurfacelist = model->nummodelsurfaces;
13541         surfacelist = model->sortedmodelsurfaces;
13542         surfaces = model->data_surfaces;
13543
13544         bih = NULL;
13545         bih_triangles_count = -1;
13546         if(!dynamic)
13547         {
13548                 if(model->render_bih.numleafs)
13549                         bih = &model->render_bih;
13550                 else if(model->collision_bih.numleafs)
13551                         bih = &model->collision_bih;
13552         }
13553         if(bih)
13554                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13555         if(bih_triangles_count == 0)
13556                 return;
13557         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13558                 return;
13559         if(bih_triangles_count > 0)
13560         {
13561                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13562                 {
13563                         surfaceindex = bih_surfaces[triangleindex];
13564                         surface = surfaces + surfaceindex;
13565                         texture = surface->texture;
13566                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13567                                 continue;
13568                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13569                                 continue;
13570                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13571                 }
13572         }
13573         else
13574         {
13575                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13576                 {
13577                         surfaceindex = surfacelist[surfacelistindex];
13578                         surface = surfaces + surfaceindex;
13579                         // check cull box first because it rejects more than any other check
13580                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13581                                 continue;
13582                         // skip transparent surfaces
13583                         texture = surface->texture;
13584                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13585                                 continue;
13586                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13587                                 continue;
13588                         numtriangles = surface->num_triangles;
13589                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13590                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13591                 }
13592         }
13593 }
13594
13595 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13596 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)
13597 {
13598         int renderentityindex;
13599         float worldmins[3];
13600         float worldmaxs[3];
13601         entity_render_t *ent;
13602
13603         if (!cl_decals_newsystem.integer)
13604                 return;
13605
13606         worldmins[0] = worldorigin[0] - worldsize;
13607         worldmins[1] = worldorigin[1] - worldsize;
13608         worldmins[2] = worldorigin[2] - worldsize;
13609         worldmaxs[0] = worldorigin[0] + worldsize;
13610         worldmaxs[1] = worldorigin[1] + worldsize;
13611         worldmaxs[2] = worldorigin[2] + worldsize;
13612
13613         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13614
13615         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13616         {
13617                 ent = r_refdef.scene.entities[renderentityindex];
13618                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13619                         continue;
13620
13621                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13622         }
13623 }
13624
13625 typedef struct r_decalsystem_splatqueue_s
13626 {
13627         vec3_t worldorigin;
13628         vec3_t worldnormal;
13629         float color[4];
13630         float tcrange[4];
13631         float worldsize;
13632         int decalsequence;
13633 }
13634 r_decalsystem_splatqueue_t;
13635
13636 int r_decalsystem_numqueued = 0;
13637 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13638
13639 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)
13640 {
13641         r_decalsystem_splatqueue_t *queue;
13642
13643         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13644                 return;
13645
13646         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13647         VectorCopy(worldorigin, queue->worldorigin);
13648         VectorCopy(worldnormal, queue->worldnormal);
13649         Vector4Set(queue->color, r, g, b, a);
13650         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13651         queue->worldsize = worldsize;
13652         queue->decalsequence = cl.decalsequence++;
13653 }
13654
13655 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13656 {
13657         int i;
13658         r_decalsystem_splatqueue_t *queue;
13659
13660         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13661                 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);
13662         r_decalsystem_numqueued = 0;
13663 }
13664
13665 extern cvar_t cl_decals_max;
13666 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13667 {
13668         int i;
13669         decalsystem_t *decalsystem = &ent->decalsystem;
13670         int numdecals;
13671         int killsequence;
13672         tridecal_t *decal;
13673         float frametime;
13674         float lifetime;
13675
13676         if (!decalsystem->numdecals)
13677                 return;
13678
13679         if (r_showsurfaces.integer)
13680                 return;
13681
13682         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13683         {
13684                 R_DecalSystem_Reset(decalsystem);
13685                 return;
13686         }
13687
13688         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13689         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13690
13691         if (decalsystem->lastupdatetime)
13692                 frametime = (cl.time - decalsystem->lastupdatetime);
13693         else
13694                 frametime = 0;
13695         decalsystem->lastupdatetime = cl.time;
13696         decal = decalsystem->decals;
13697         numdecals = decalsystem->numdecals;
13698
13699         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13700         {
13701                 if (decal->color4ub[0][3])
13702                 {
13703                         decal->lived += frametime;
13704                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13705                         {
13706                                 memset(decal, 0, sizeof(*decal));
13707                                 if (decalsystem->freedecal > i)
13708                                         decalsystem->freedecal = i;
13709                         }
13710                 }
13711         }
13712         decal = decalsystem->decals;
13713         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13714                 numdecals--;
13715
13716         // collapse the array by shuffling the tail decals into the gaps
13717         for (;;)
13718         {
13719                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13720                         decalsystem->freedecal++;
13721                 if (decalsystem->freedecal == numdecals)
13722                         break;
13723                 decal[decalsystem->freedecal] = decal[--numdecals];
13724         }
13725
13726         decalsystem->numdecals = numdecals;
13727
13728         if (numdecals <= 0)
13729         {
13730                 // if there are no decals left, reset decalsystem
13731                 R_DecalSystem_Reset(decalsystem);
13732         }
13733 }
13734
13735 extern skinframe_t *decalskinframe;
13736 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13737 {
13738         int i;
13739         decalsystem_t *decalsystem = &ent->decalsystem;
13740         int numdecals;
13741         tridecal_t *decal;
13742         float faderate;
13743         float alpha;
13744         float *v3f;
13745         float *c4f;
13746         float *t2f;
13747         const int *e;
13748         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13749         int numtris = 0;
13750
13751         numdecals = decalsystem->numdecals;
13752         if (!numdecals)
13753                 return;
13754
13755         if (r_showsurfaces.integer)
13756                 return;
13757
13758         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13759         {
13760                 R_DecalSystem_Reset(decalsystem);
13761                 return;
13762         }
13763
13764         // if the model is static it doesn't matter what value we give for
13765         // wantnormals and wanttangents, so this logic uses only rules applicable
13766         // to a model, knowing that they are meaningless otherwise
13767         if (ent == r_refdef.scene.worldentity)
13768                 RSurf_ActiveWorldEntity();
13769         else
13770                 RSurf_ActiveModelEntity(ent, false, false, false);
13771
13772         decalsystem->lastupdatetime = cl.time;
13773         decal = decalsystem->decals;
13774
13775         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13776
13777         // update vertex positions for animated models
13778         v3f = decalsystem->vertex3f;
13779         c4f = decalsystem->color4f;
13780         t2f = decalsystem->texcoord2f;
13781         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13782         {
13783                 if (!decal->color4ub[0][3])
13784                         continue;
13785
13786                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13787                         continue;
13788
13789                 // update color values for fading decals
13790                 if (decal->lived >= cl_decals_time.value)
13791                 {
13792                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13793                         alpha *= (1.0f/255.0f);
13794                 }
13795                 else
13796                         alpha = 1.0f/255.0f;
13797
13798                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13799                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13800                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13801                 c4f[ 3] = 1;
13802                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13803                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13804                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13805                 c4f[ 7] = 1;
13806                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13807                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13808                 c4f[10] = decal->color4ub[2][2] * alpha;
13809                 c4f[11] = 1;
13810
13811                 t2f[0] = decal->texcoord2f[0][0];
13812                 t2f[1] = decal->texcoord2f[0][1];
13813                 t2f[2] = decal->texcoord2f[1][0];
13814                 t2f[3] = decal->texcoord2f[1][1];
13815                 t2f[4] = decal->texcoord2f[2][0];
13816                 t2f[5] = decal->texcoord2f[2][1];
13817
13818                 // update vertex positions for animated models
13819                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13820                 {
13821                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13822                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13823                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13824                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13825                 }
13826                 else
13827                 {
13828                         VectorCopy(decal->vertex3f[0], v3f);
13829                         VectorCopy(decal->vertex3f[1], v3f + 3);
13830                         VectorCopy(decal->vertex3f[2], v3f + 6);
13831                 }
13832
13833                 if (r_refdef.fogenabled)
13834                 {
13835                         alpha = RSurf_FogVertex(v3f);
13836                         VectorScale(c4f, alpha, c4f);
13837                         alpha = RSurf_FogVertex(v3f + 3);
13838                         VectorScale(c4f + 4, alpha, c4f + 4);
13839                         alpha = RSurf_FogVertex(v3f + 6);
13840                         VectorScale(c4f + 8, alpha, c4f + 8);
13841                 }
13842
13843                 v3f += 9;
13844                 c4f += 12;
13845                 t2f += 6;
13846                 numtris++;
13847         }
13848
13849         if (numtris > 0)
13850         {
13851                 r_refdef.stats.drawndecals += numtris;
13852
13853                 // now render the decals all at once
13854                 // (this assumes they all use one particle font texture!)
13855                 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);
13856                 R_Mesh_ResetTextureState();
13857                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13858                 GL_DepthMask(false);
13859                 GL_DepthRange(0, 1);
13860                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13861                 GL_DepthTest(true);
13862                 GL_CullFace(GL_NONE);
13863                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13864                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13865                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13866         }
13867 }
13868
13869 static void R_DrawModelDecals(void)
13870 {
13871         int i, numdecals;
13872
13873         // fade faster when there are too many decals
13874         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13875         for (i = 0;i < r_refdef.scene.numentities;i++)
13876                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13877
13878         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13879         for (i = 0;i < r_refdef.scene.numentities;i++)
13880                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13881                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13882
13883         R_DecalSystem_ApplySplatEntitiesQueue();
13884
13885         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13886         for (i = 0;i < r_refdef.scene.numentities;i++)
13887                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13888
13889         r_refdef.stats.totaldecals += numdecals;
13890
13891         if (r_showsurfaces.integer)
13892                 return;
13893
13894         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13895
13896         for (i = 0;i < r_refdef.scene.numentities;i++)
13897         {
13898                 if (!r_refdef.viewcache.entityvisible[i])
13899                         continue;
13900                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13901                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13902         }
13903 }
13904
13905 extern cvar_t mod_collision_bih;
13906 void R_DrawDebugModel(void)
13907 {
13908         entity_render_t *ent = rsurface.entity;
13909         int i, j, k, l, flagsmask;
13910         const msurface_t *surface;
13911         dp_model_t *model = ent->model;
13912         vec3_t v;
13913
13914         switch(vid.renderpath)
13915         {
13916         case RENDERPATH_GL11:
13917         case RENDERPATH_GL13:
13918         case RENDERPATH_GL20:
13919         case RENDERPATH_CGGL:
13920                 break;
13921         case RENDERPATH_D3D9:
13922                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13923                 return;
13924         case RENDERPATH_D3D10:
13925                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13926                 return;
13927         case RENDERPATH_D3D11:
13928                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13929                 return;
13930         }
13931
13932         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13933
13934         R_Mesh_ResetTextureState();
13935         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13936         GL_DepthRange(0, 1);
13937         GL_DepthTest(!r_showdisabledepthtest.integer);
13938         GL_DepthMask(false);
13939         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13940
13941         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13942         {
13943                 int triangleindex;
13944                 int bihleafindex;
13945                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13946                 const q3mbrush_t *brush;
13947                 const bih_t *bih = &model->collision_bih;
13948                 const bih_leaf_t *bihleaf;
13949                 float vertex3f[3][3];
13950                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13951                 cullbox = false;
13952                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13953                 {
13954                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13955                                 continue;
13956                         switch (bihleaf->type)
13957                         {
13958                         case BIH_BRUSH:
13959                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13960                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13961                                 {
13962                                         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);
13963                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13964                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13965                                 }
13966                                 break;
13967                         case BIH_COLLISIONTRIANGLE:
13968                                 triangleindex = bihleaf->itemindex;
13969                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13970                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13971                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13972                                 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);
13973                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13974                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13975                                 break;
13976                         case BIH_RENDERTRIANGLE:
13977                                 triangleindex = bihleaf->itemindex;
13978                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13979                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13980                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13981                                 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);
13982                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13983                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13984                                 break;
13985                         }
13986                 }
13987         }
13988
13989         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13990
13991         if (r_showtris.integer || r_shownormals.integer)
13992         {
13993                 if (r_showdisabledepthtest.integer)
13994                 {
13995                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13996                         GL_DepthMask(false);
13997                 }
13998                 else
13999                 {
14000                         GL_BlendFunc(GL_ONE, GL_ZERO);
14001                         GL_DepthMask(true);
14002                 }
14003                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14004                 {
14005                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14006                                 continue;
14007                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14008                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14009                         {
14010                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14011                                 if (r_showtris.value > 0)
14012                                 {
14013                                         if (!rsurface.texture->currentlayers->depthmask)
14014                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14015                                         else if (ent == r_refdef.scene.worldentity)
14016                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14017                                         else
14018                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14019                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14020                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14021                                         RSurf_DrawBatch();
14022                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14023                                         CHECKGLERROR
14024                                 }
14025                                 if (r_shownormals.value < 0)
14026                                 {
14027                                         qglBegin(GL_LINES);
14028                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14029                                         {
14030                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14031                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14032                                                 qglVertex3f(v[0], v[1], v[2]);
14033                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14034                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14035                                                 qglVertex3f(v[0], v[1], v[2]);
14036                                         }
14037                                         qglEnd();
14038                                         CHECKGLERROR
14039                                 }
14040                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14041                                 {
14042                                         qglBegin(GL_LINES);
14043                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14044                                         {
14045                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14046                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14047                                                 qglVertex3f(v[0], v[1], v[2]);
14048                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14049                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14050                                                 qglVertex3f(v[0], v[1], v[2]);
14051                                         }
14052                                         qglEnd();
14053                                         CHECKGLERROR
14054                                         qglBegin(GL_LINES);
14055                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14056                                         {
14057                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14058                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14059                                                 qglVertex3f(v[0], v[1], v[2]);
14060                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14061                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14062                                                 qglVertex3f(v[0], v[1], v[2]);
14063                                         }
14064                                         qglEnd();
14065                                         CHECKGLERROR
14066                                         qglBegin(GL_LINES);
14067                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14068                                         {
14069                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14070                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14071                                                 qglVertex3f(v[0], v[1], v[2]);
14072                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14073                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14074                                                 qglVertex3f(v[0], v[1], v[2]);
14075                                         }
14076                                         qglEnd();
14077                                         CHECKGLERROR
14078                                 }
14079                         }
14080                 }
14081                 rsurface.texture = NULL;
14082         }
14083 }
14084
14085 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14086 int r_maxsurfacelist = 0;
14087 const msurface_t **r_surfacelist = NULL;
14088 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14089 {
14090         int i, j, endj, flagsmask;
14091         dp_model_t *model = r_refdef.scene.worldmodel;
14092         msurface_t *surfaces;
14093         unsigned char *update;
14094         int numsurfacelist = 0;
14095         if (model == NULL)
14096                 return;
14097
14098         if (r_maxsurfacelist < model->num_surfaces)
14099         {
14100                 r_maxsurfacelist = model->num_surfaces;
14101                 if (r_surfacelist)
14102                         Mem_Free((msurface_t**)r_surfacelist);
14103                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14104         }
14105
14106         RSurf_ActiveWorldEntity();
14107
14108         surfaces = model->data_surfaces;
14109         update = model->brushq1.lightmapupdateflags;
14110
14111         // update light styles on this submodel
14112         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14113         {
14114                 model_brush_lightstyleinfo_t *style;
14115                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14116                 {
14117                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14118                         {
14119                                 int *list = style->surfacelist;
14120                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14121                                 for (j = 0;j < style->numsurfaces;j++)
14122                                         update[list[j]] = true;
14123                         }
14124                 }
14125         }
14126
14127         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14128
14129         if (debug)
14130         {
14131                 R_DrawDebugModel();
14132                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14133                 return;
14134         }
14135
14136         rsurface.lightmaptexture = NULL;
14137         rsurface.deluxemaptexture = NULL;
14138         rsurface.uselightmaptexture = false;
14139         rsurface.texture = NULL;
14140         rsurface.rtlight = NULL;
14141         numsurfacelist = 0;
14142         // add visible surfaces to draw list
14143         for (i = 0;i < model->nummodelsurfaces;i++)
14144         {
14145                 j = model->sortedmodelsurfaces[i];
14146                 if (r_refdef.viewcache.world_surfacevisible[j])
14147                         r_surfacelist[numsurfacelist++] = surfaces + j;
14148         }
14149         // update lightmaps if needed
14150         if (model->brushq1.firstrender)
14151         {
14152                 model->brushq1.firstrender = false;
14153                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14154                         if (update[j])
14155                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14156         }
14157         else if (update)
14158         {
14159                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14160                         if (r_refdef.viewcache.world_surfacevisible[j])
14161                                 if (update[j])
14162                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14163         }
14164         // don't do anything if there were no surfaces
14165         if (!numsurfacelist)
14166         {
14167                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14168                 return;
14169         }
14170         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14171         GL_AlphaTest(false);
14172
14173         // add to stats if desired
14174         if (r_speeds.integer && !skysurfaces && !depthonly)
14175         {
14176                 r_refdef.stats.world_surfaces += numsurfacelist;
14177                 for (j = 0;j < numsurfacelist;j++)
14178                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14179         }
14180
14181         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14182 }
14183
14184 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14185 {
14186         int i, j, endj, flagsmask;
14187         dp_model_t *model = ent->model;
14188         msurface_t *surfaces;
14189         unsigned char *update;
14190         int numsurfacelist = 0;
14191         if (model == NULL)
14192                 return;
14193
14194         if (r_maxsurfacelist < model->num_surfaces)
14195         {
14196                 r_maxsurfacelist = model->num_surfaces;
14197                 if (r_surfacelist)
14198                         Mem_Free((msurface_t **)r_surfacelist);
14199                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14200         }
14201
14202         // if the model is static it doesn't matter what value we give for
14203         // wantnormals and wanttangents, so this logic uses only rules applicable
14204         // to a model, knowing that they are meaningless otherwise
14205         if (ent == r_refdef.scene.worldentity)
14206                 RSurf_ActiveWorldEntity();
14207         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14208                 RSurf_ActiveModelEntity(ent, false, false, false);
14209         else if (prepass)
14210                 RSurf_ActiveModelEntity(ent, true, true, true);
14211         else if (depthonly)
14212         {
14213                 switch (vid.renderpath)
14214                 {
14215                 case RENDERPATH_GL20:
14216                 case RENDERPATH_CGGL:
14217                 case RENDERPATH_D3D9:
14218                 case RENDERPATH_D3D10:
14219                 case RENDERPATH_D3D11:
14220                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14221                         break;
14222                 case RENDERPATH_GL13:
14223                 case RENDERPATH_GL11:
14224                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14225                         break;
14226                 }
14227         }
14228         else
14229         {
14230                 switch (vid.renderpath)
14231                 {
14232                 case RENDERPATH_GL20:
14233                 case RENDERPATH_CGGL:
14234                 case RENDERPATH_D3D9:
14235                 case RENDERPATH_D3D10:
14236                 case RENDERPATH_D3D11:
14237                         RSurf_ActiveModelEntity(ent, true, true, false);
14238                         break;
14239                 case RENDERPATH_GL13:
14240                 case RENDERPATH_GL11:
14241                         RSurf_ActiveModelEntity(ent, true, false, false);
14242                         break;
14243                 }
14244         }
14245
14246         surfaces = model->data_surfaces;
14247         update = model->brushq1.lightmapupdateflags;
14248
14249         // update light styles
14250         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14251         {
14252                 model_brush_lightstyleinfo_t *style;
14253                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14254                 {
14255                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14256                         {
14257                                 int *list = style->surfacelist;
14258                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14259                                 for (j = 0;j < style->numsurfaces;j++)
14260                                         update[list[j]] = true;
14261                         }
14262                 }
14263         }
14264
14265         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14266
14267         if (debug)
14268         {
14269                 R_DrawDebugModel();
14270                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14271                 return;
14272         }
14273
14274         rsurface.lightmaptexture = NULL;
14275         rsurface.deluxemaptexture = NULL;
14276         rsurface.uselightmaptexture = false;
14277         rsurface.texture = NULL;
14278         rsurface.rtlight = NULL;
14279         numsurfacelist = 0;
14280         // add visible surfaces to draw list
14281         for (i = 0;i < model->nummodelsurfaces;i++)
14282                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14283         // don't do anything if there were no surfaces
14284         if (!numsurfacelist)
14285         {
14286                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14287                 return;
14288         }
14289         // update lightmaps if needed
14290         if (update)
14291         {
14292                 int updated = 0;
14293                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14294                 {
14295                         if (update[j])
14296                         {
14297                                 updated++;
14298                                 R_BuildLightMap(ent, surfaces + j);
14299                         }
14300                 }
14301         }
14302         if (update)
14303                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14304                         if (update[j])
14305                                 R_BuildLightMap(ent, surfaces + j);
14306         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14307         GL_AlphaTest(false);
14308
14309         // add to stats if desired
14310         if (r_speeds.integer && !skysurfaces && !depthonly)
14311         {
14312                 r_refdef.stats.entities_surfaces += numsurfacelist;
14313                 for (j = 0;j < numsurfacelist;j++)
14314                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14315         }
14316
14317         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14318 }
14319
14320 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14321 {
14322         static texture_t texture;
14323         static msurface_t surface;
14324         const msurface_t *surfacelist = &surface;
14325
14326         // fake enough texture and surface state to render this geometry
14327
14328         texture.update_lastrenderframe = -1; // regenerate this texture
14329         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14330         texture.currentskinframe = skinframe;
14331         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14332         texture.offsetmapping = OFFSETMAPPING_OFF;
14333         texture.offsetscale = 1;
14334         texture.specularscalemod = 1;
14335         texture.specularpowermod = 1;
14336
14337         surface.texture = &texture;
14338         surface.num_triangles = numtriangles;
14339         surface.num_firsttriangle = firsttriangle;
14340         surface.num_vertices = numvertices;
14341         surface.num_firstvertex = firstvertex;
14342
14343         // now render it
14344         rsurface.texture = R_GetCurrentTexture(surface.texture);
14345         rsurface.lightmaptexture = NULL;
14346         rsurface.deluxemaptexture = NULL;
14347         rsurface.uselightmaptexture = false;
14348         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14349 }
14350
14351 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)
14352 {
14353         static msurface_t surface;
14354         const msurface_t *surfacelist = &surface;
14355
14356         // fake enough texture and surface state to render this geometry
14357
14358         surface.texture = texture;
14359         surface.num_triangles = numtriangles;
14360         surface.num_firsttriangle = firsttriangle;
14361         surface.num_vertices = numvertices;
14362         surface.num_firstvertex = firstvertex;
14363
14364         // now render it
14365         rsurface.texture = R_GetCurrentTexture(surface.texture);
14366         rsurface.lightmaptexture = NULL;
14367         rsurface.deluxemaptexture = NULL;
14368         rsurface.uselightmaptexture = false;
14369         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14370 }