]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix water rendering bugs (was rendering water surface over its own view)
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 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)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 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"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 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)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 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"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 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)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 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"};
70 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"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 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"};
73 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"};
74 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"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 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)"};
80 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)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 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."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 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."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 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"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 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"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 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)"};
113 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"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
128
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
152
153 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"};
154
155 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"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
166 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)"};
167
168 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
169
170 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)"};
171
172 extern cvar_t v_glslgamma;
173
174 extern qboolean v_flipped_state;
175
176 static struct r_bloomstate_s
177 {
178         qboolean enabled;
179         qboolean hdr;
180
181         int bloomwidth, bloomheight;
182
183         int screentexturewidth, screentextureheight;
184         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
185
186         int bloomtexturewidth, bloomtextureheight;
187         rtexture_t *texture_bloom;
188
189         // arrays for rendering the screen passes
190         float screentexcoord2f[8];
191         float bloomtexcoord2f[8];
192         float offsettexcoord2f[8];
193
194         r_viewport_t viewport;
195 }
196 r_bloomstate;
197
198 r_waterstate_t r_waterstate;
199
200 /// shadow volume bsp struct with automatically growing nodes buffer
201 svbsp_t r_svbsp;
202
203 rtexture_t *r_texture_blanknormalmap;
204 rtexture_t *r_texture_white;
205 rtexture_t *r_texture_grey128;
206 rtexture_t *r_texture_black;
207 rtexture_t *r_texture_notexture;
208 rtexture_t *r_texture_whitecube;
209 rtexture_t *r_texture_normalizationcube;
210 rtexture_t *r_texture_fogattenuation;
211 rtexture_t *r_texture_gammaramps;
212 unsigned int r_texture_gammaramps_serial;
213 //rtexture_t *r_texture_fogintensity;
214
215 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
216 unsigned int r_numqueries;
217 unsigned int r_maxqueries;
218
219 typedef struct r_qwskincache_s
220 {
221         char name[MAX_QPATH];
222         skinframe_t *skinframe;
223 }
224 r_qwskincache_t;
225
226 static r_qwskincache_t *r_qwskincache;
227 static int r_qwskincache_size;
228
229 /// vertex coordinates for a quad that covers the screen exactly
230 const float r_screenvertex3f[12] =
231 {
232         0, 0, 0,
233         1, 0, 0,
234         1, 1, 0,
235         0, 1, 0
236 };
237
238 extern void R_DrawModelShadows(void);
239
240 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
241 {
242         int i;
243         for (i = 0;i < verts;i++)
244         {
245                 out[0] = in[0] * r;
246                 out[1] = in[1] * g;
247                 out[2] = in[2] * b;
248                 out[3] = in[3];
249                 in += 4;
250                 out += 4;
251         }
252 }
253
254 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
255 {
256         int i;
257         for (i = 0;i < verts;i++)
258         {
259                 out[0] = r;
260                 out[1] = g;
261                 out[2] = b;
262                 out[3] = a;
263                 out += 4;
264         }
265 }
266
267 // FIXME: move this to client?
268 void FOG_clear(void)
269 {
270         if (gamemode == GAME_NEHAHRA)
271         {
272                 Cvar_Set("gl_fogenable", "0");
273                 Cvar_Set("gl_fogdensity", "0.2");
274                 Cvar_Set("gl_fogred", "0.3");
275                 Cvar_Set("gl_foggreen", "0.3");
276                 Cvar_Set("gl_fogblue", "0.3");
277         }
278         r_refdef.fog_density = 0;
279         r_refdef.fog_red = 0;
280         r_refdef.fog_green = 0;
281         r_refdef.fog_blue = 0;
282         r_refdef.fog_alpha = 1;
283         r_refdef.fog_start = 0;
284         r_refdef.fog_end = 16384;
285         r_refdef.fog_height = 1<<30;
286         r_refdef.fog_fadedepth = 128;
287 }
288
289 static void R_BuildBlankTextures(void)
290 {
291         unsigned char data[4];
292         data[2] = 128; // normal X
293         data[1] = 128; // normal Y
294         data[0] = 255; // normal Z
295         data[3] = 128; // height
296         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
297         data[0] = 255;
298         data[1] = 255;
299         data[2] = 255;
300         data[3] = 255;
301         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
302         data[0] = 128;
303         data[1] = 128;
304         data[2] = 128;
305         data[3] = 255;
306         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
307         data[0] = 0;
308         data[1] = 0;
309         data[2] = 0;
310         data[3] = 255;
311         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
312 }
313
314 static void R_BuildNoTexture(void)
315 {
316         int x, y;
317         unsigned char pix[16][16][4];
318         // this makes a light grey/dark grey checkerboard texture
319         for (y = 0;y < 16;y++)
320         {
321                 for (x = 0;x < 16;x++)
322                 {
323                         if ((y < 8) ^ (x < 8))
324                         {
325                                 pix[y][x][0] = 128;
326                                 pix[y][x][1] = 128;
327                                 pix[y][x][2] = 128;
328                                 pix[y][x][3] = 255;
329                         }
330                         else
331                         {
332                                 pix[y][x][0] = 64;
333                                 pix[y][x][1] = 64;
334                                 pix[y][x][2] = 64;
335                                 pix[y][x][3] = 255;
336                         }
337                 }
338         }
339         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
340 }
341
342 static void R_BuildWhiteCube(void)
343 {
344         unsigned char data[6*1*1*4];
345         memset(data, 255, sizeof(data));
346         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
347 }
348
349 static void R_BuildNormalizationCube(void)
350 {
351         int x, y, side;
352         vec3_t v;
353         vec_t s, t, intensity;
354 #define NORMSIZE 64
355         unsigned char *data;
356         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
357         for (side = 0;side < 6;side++)
358         {
359                 for (y = 0;y < NORMSIZE;y++)
360                 {
361                         for (x = 0;x < NORMSIZE;x++)
362                         {
363                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
364                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
365                                 switch(side)
366                                 {
367                                 default:
368                                 case 0:
369                                         v[0] = 1;
370                                         v[1] = -t;
371                                         v[2] = -s;
372                                         break;
373                                 case 1:
374                                         v[0] = -1;
375                                         v[1] = -t;
376                                         v[2] = s;
377                                         break;
378                                 case 2:
379                                         v[0] = s;
380                                         v[1] = 1;
381                                         v[2] = t;
382                                         break;
383                                 case 3:
384                                         v[0] = s;
385                                         v[1] = -1;
386                                         v[2] = -t;
387                                         break;
388                                 case 4:
389                                         v[0] = s;
390                                         v[1] = -t;
391                                         v[2] = 1;
392                                         break;
393                                 case 5:
394                                         v[0] = -s;
395                                         v[1] = -t;
396                                         v[2] = -1;
397                                         break;
398                                 }
399                                 intensity = 127.0f / sqrt(DotProduct(v, v));
400                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
401                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
402                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
403                                 data[((side*64+y)*64+x)*4+3] = 255;
404                         }
405                 }
406         }
407         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
408         Mem_Free(data);
409 }
410
411 static void R_BuildFogTexture(void)
412 {
413         int x, b;
414 #define FOGWIDTH 256
415         unsigned char data1[FOGWIDTH][4];
416         //unsigned char data2[FOGWIDTH][4];
417         double d, r, alpha;
418
419         r_refdef.fogmasktable_start = r_refdef.fog_start;
420         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
421         r_refdef.fogmasktable_range = r_refdef.fogrange;
422         r_refdef.fogmasktable_density = r_refdef.fog_density;
423
424         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
425         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
426         {
427                 d = (x * r - r_refdef.fogmasktable_start);
428                 if(developer_extra.integer)
429                         Con_DPrintf("%f ", d);
430                 d = max(0, d);
431                 if (r_fog_exp2.integer)
432                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
433                 else
434                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
435                 if(developer_extra.integer)
436                         Con_DPrintf(" : %f ", alpha);
437                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
438                 if(developer_extra.integer)
439                         Con_DPrintf(" = %f\n", alpha);
440                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
441         }
442
443         for (x = 0;x < FOGWIDTH;x++)
444         {
445                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
446                 data1[x][0] = b;
447                 data1[x][1] = b;
448                 data1[x][2] = b;
449                 data1[x][3] = 255;
450                 //data2[x][0] = 255 - b;
451                 //data2[x][1] = 255 - b;
452                 //data2[x][2] = 255 - b;
453                 //data2[x][3] = 255;
454         }
455         if (r_texture_fogattenuation)
456         {
457                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
458                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
459         }
460         else
461         {
462                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
463                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
464         }
465 }
466
467 //=======================================================================================================================================================
468
469 static const char *builtinshaderstring =
470 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
471 "// written by Forest 'LordHavoc' Hale\n"
472 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
473 "\n"
474 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
475 "# define USEFOG\n"
476 "#endif\n"
477 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
478 "#define USELIGHTMAP\n"
479 "#endif\n"
480 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
481 "#define USEEYEVECTOR\n"
482 "#endif\n"
483 "\n"
484 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
485 "# extension GL_ARB_texture_rectangle : enable\n"
486 "#endif\n"
487 "\n"
488 "#ifdef USESHADOWMAP2D\n"
489 "# ifdef GL_EXT_gpu_shader4\n"
490 "#   extension GL_EXT_gpu_shader4 : enable\n"
491 "# endif\n"
492 "# ifdef GL_ARB_texture_gather\n"
493 "#   extension GL_ARB_texture_gather : enable\n"
494 "# else\n"
495 "#   ifdef GL_AMD_texture_texture4\n"
496 "#     extension GL_AMD_texture_texture4 : enable\n"
497 "#   endif\n"
498 "# endif\n"
499 "#endif\n"
500 "\n"
501 "#ifdef USESHADOWMAPCUBE\n"
502 "# extension GL_EXT_gpu_shader4 : enable\n"
503 "#endif\n"
504 "\n"
505 "//#ifdef USESHADOWSAMPLER\n"
506 "//# extension GL_ARB_shadow : enable\n"
507 "//#endif\n"
508 "\n"
509 "//#ifdef __GLSL_CG_DATA_TYPES\n"
510 "//# define myhalf half\n"
511 "//# define myhalf2 half2\n"
512 "//# define myhalf3 half3\n"
513 "//# define myhalf4 half4\n"
514 "//#else\n"
515 "# define myhalf float\n"
516 "# define myhalf2 vec2\n"
517 "# define myhalf3 vec3\n"
518 "# define myhalf4 vec4\n"
519 "//#endif\n"
520 "\n"
521 "#ifdef VERTEX_SHADER\n"
522 "uniform mat4 ModelViewProjectionMatrix;\n"
523 "#endif\n"
524 "\n"
525 "#ifdef MODE_DEPTH_OR_SHADOW\n"
526 "#ifdef VERTEX_SHADER\n"
527 "void main(void)\n"
528 "{\n"
529 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
530 "}\n"
531 "#endif\n"
532 "#else // !MODE_DEPTH_ORSHADOW\n"
533 "\n"
534 "\n"
535 "\n"
536 "\n"
537 "#ifdef MODE_SHOWDEPTH\n"
538 "#ifdef VERTEX_SHADER\n"
539 "void main(void)\n"
540 "{\n"
541 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
542 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
543 "}\n"
544 "#endif\n"
545 "\n"
546 "#ifdef FRAGMENT_SHADER\n"
547 "void main(void)\n"
548 "{\n"
549 "       gl_FragColor = gl_Color;\n"
550 "}\n"
551 "#endif\n"
552 "#else // !MODE_SHOWDEPTH\n"
553 "\n"
554 "\n"
555 "\n"
556 "\n"
557 "#ifdef MODE_POSTPROCESS\n"
558 "varying vec2 TexCoord1;\n"
559 "varying vec2 TexCoord2;\n"
560 "\n"
561 "#ifdef VERTEX_SHADER\n"
562 "void main(void)\n"
563 "{\n"
564 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
565 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
566 "#ifdef USEBLOOM\n"
567 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
568 "#endif\n"
569 "}\n"
570 "#endif\n"
571 "\n"
572 "#ifdef FRAGMENT_SHADER\n"
573 "uniform sampler2D Texture_First;\n"
574 "#ifdef USEBLOOM\n"
575 "uniform sampler2D Texture_Second;\n"
576 "#endif\n"
577 "#ifdef USEGAMMARAMPS\n"
578 "uniform sampler2D Texture_GammaRamps;\n"
579 "#endif\n"
580 "#ifdef USESATURATION\n"
581 "uniform float Saturation;\n"
582 "#endif\n"
583 "#ifdef USEVIEWTINT\n"
584 "uniform vec4 ViewTintColor;\n"
585 "#endif\n"
586 "//uncomment these if you want to use them:\n"
587 "uniform vec4 UserVec1;\n"
588 "// uniform vec4 UserVec2;\n"
589 "// uniform vec4 UserVec3;\n"
590 "// uniform vec4 UserVec4;\n"
591 "// uniform float ClientTime;\n"
592 "uniform vec2 PixelSize;\n"
593 "void main(void)\n"
594 "{\n"
595 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
596 "#ifdef USEBLOOM\n"
597 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
598 "#endif\n"
599 "#ifdef USEVIEWTINT\n"
600 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
601 "#endif\n"
602 "\n"
603 "#ifdef USEPOSTPROCESSING\n"
604 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
605 "// 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"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
609 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
610 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
611 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
612 "#endif\n"
613 "\n"
614 "#ifdef USESATURATION\n"
615 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
616 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
617 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
618 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEGAMMARAMPS\n"
622 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
623 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
624 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
625 "#endif\n"
626 "}\n"
627 "#endif\n"
628 "#else // !MODE_POSTPROCESS\n"
629 "\n"
630 "\n"
631 "\n"
632 "\n"
633 "#ifdef MODE_GENERIC\n"
634 "#ifdef USEDIFFUSE\n"
635 "varying vec2 TexCoord1;\n"
636 "#endif\n"
637 "#ifdef USESPECULAR\n"
638 "varying vec2 TexCoord2;\n"
639 "#endif\n"
640 "#ifdef VERTEX_SHADER\n"
641 "void main(void)\n"
642 "{\n"
643 "       gl_FrontColor = gl_Color;\n"
644 "#ifdef USEDIFFUSE\n"
645 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
646 "#endif\n"
647 "#ifdef USESPECULAR\n"
648 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
649 "#endif\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "}\n"
652 "#endif\n"
653 "\n"
654 "#ifdef FRAGMENT_SHADER\n"
655 "#ifdef USEDIFFUSE\n"
656 "uniform sampler2D Texture_First;\n"
657 "#endif\n"
658 "#ifdef USESPECULAR\n"
659 "uniform sampler2D Texture_Second;\n"
660 "#endif\n"
661 "\n"
662 "void main(void)\n"
663 "{\n"
664 "       gl_FragColor = gl_Color;\n"
665 "#ifdef USEDIFFUSE\n"
666 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
667 "#endif\n"
668 "\n"
669 "#ifdef USESPECULAR\n"
670 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
671 "# ifdef USECOLORMAPPING\n"
672 "       gl_FragColor *= tex2;\n"
673 "# endif\n"
674 "# ifdef USEGLOW\n"
675 "       gl_FragColor += tex2;\n"
676 "# endif\n"
677 "# ifdef USEVERTEXTEXTUREBLEND\n"
678 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
679 "# endif\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "#else // !MODE_GENERIC\n"
684 "\n"
685 "\n"
686 "\n"
687 "\n"
688 "#ifdef MODE_BLOOMBLUR\n"
689 "varying TexCoord;\n"
690 "#ifdef VERTEX_SHADER\n"
691 "void main(void)\n"
692 "{\n"
693 "       gl_FrontColor = gl_Color;\n"
694 "       TexCoord = gl_MultiTexCoord0.xy;\n"
695 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
696 "}\n"
697 "#endif\n"
698 "\n"
699 "#ifdef FRAGMENT_SHADER\n"
700 "uniform sampler2D Texture_First;\n"
701 "uniform vec4 BloomBlur_Parameters;\n"
702 "\n"
703 "void main(void)\n"
704 "{\n"
705 "       int i;\n"
706 "       vec2 tc = TexCoord;\n"
707 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
708 "       tc += BloomBlur_Parameters.xy;\n"
709 "       for (i = 1;i < SAMPLES;i++)\n"
710 "       {\n"
711 "               color += texture2D(Texture_First, tc).rgb;\n"
712 "               tc += BloomBlur_Parameters.xy;\n"
713 "       }\n"
714 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
715 "}\n"
716 "#endif\n"
717 "#else // !MODE_BLOOMBLUR\n"
718 "#ifdef MODE_REFRACTION\n"
719 "varying vec2 TexCoord;\n"
720 "varying vec4 ModelViewProjectionPosition;\n"
721 "uniform mat4 TexMatrix;\n"
722 "#ifdef VERTEX_SHADER\n"
723 "\n"
724 "void main(void)\n"
725 "{\n"
726 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
727 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
728 "       ModelViewProjectionPosition = gl_Position;\n"
729 "}\n"
730 "#endif\n"
731 "\n"
732 "#ifdef FRAGMENT_SHADER\n"
733 "uniform sampler2D Texture_Normal;\n"
734 "uniform sampler2D Texture_Refraction;\n"
735 "uniform sampler2D Texture_Reflection;\n"
736 "\n"
737 "uniform vec4 DistortScaleRefractReflect;\n"
738 "uniform vec4 ScreenScaleRefractReflect;\n"
739 "uniform vec4 ScreenCenterRefractReflect;\n"
740 "uniform vec4 RefractColor;\n"
741 "uniform vec4 ReflectColor;\n"
742 "uniform float ReflectFactor;\n"
743 "uniform float ReflectOffset;\n"
744 "\n"
745 "void main(void)\n"
746 "{\n"
747 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
748 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
749 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
750 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
751 "       // FIXME temporary hack to detect the case that the reflection\n"
752 "       // gets blackened at edges due to leaving the area that contains actual\n"
753 "       // content.\n"
754 "       // Remove this 'ack once we have a better way to stop this thing from\n"
755 "       // 'appening.\n"
756 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
757 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
758 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
759 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
760 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
761 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
762 "}\n"
763 "#endif\n"
764 "#else // !MODE_REFRACTION\n"
765 "\n"
766 "\n"
767 "\n"
768 "\n"
769 "#ifdef MODE_WATER\n"
770 "varying vec2 TexCoord;\n"
771 "varying vec3 EyeVector;\n"
772 "varying vec4 ModelViewProjectionPosition;\n"
773 "#ifdef VERTEX_SHADER\n"
774 "uniform vec3 EyePosition;\n"
775 "uniform mat4 TexMatrix;\n"
776 "\n"
777 "void main(void)\n"
778 "{\n"
779 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
780 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
781 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
782 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
783 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
784 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
785 "       ModelViewProjectionPosition = gl_Position;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_Normal;\n"
791 "uniform sampler2D Texture_Refraction;\n"
792 "uniform sampler2D Texture_Reflection;\n"
793 "\n"
794 "uniform vec4 DistortScaleRefractReflect;\n"
795 "uniform vec4 ScreenScaleRefractReflect;\n"
796 "uniform vec4 ScreenCenterRefractReflect;\n"
797 "uniform vec4 RefractColor;\n"
798 "uniform vec4 ReflectColor;\n"
799 "uniform float ReflectFactor;\n"
800 "uniform float ReflectOffset;\n"
801 "\n"
802 "void main(void)\n"
803 "{\n"
804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
806 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
807 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
808 "       // FIXME temporary hack to detect the case that the reflection\n"
809 "       // gets blackened at edges due to leaving the area that contains actual\n"
810 "       // content.\n"
811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
812 "       // 'appening.\n"
813 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
814 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
815 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
817 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
818 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
819 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
822 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
823 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
824 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_WATER\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "// common definitions between vertex shader and fragment shader:\n"
833 "\n"
834 "varying vec2 TexCoord;\n"
835 "#ifdef USEVERTEXTEXTUREBLEND\n"
836 "varying vec2 TexCoord2;\n"
837 "#endif\n"
838 "#ifdef USELIGHTMAP\n"
839 "varying vec2 TexCoordLightmap;\n"
840 "#endif\n"
841 "\n"
842 "#ifdef MODE_LIGHTSOURCE\n"
843 "varying vec3 CubeVector;\n"
844 "#endif\n"
845 "\n"
846 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
847 "varying vec3 LightVector;\n"
848 "#endif\n"
849 "\n"
850 "#ifdef USEEYEVECTOR\n"
851 "varying vec3 EyeVector;\n"
852 "#endif\n"
853 "#ifdef USEFOG\n"
854 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
855 "#endif\n"
856 "\n"
857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
858 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
859 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
860 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEREFLECTION\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "#endif\n"
866 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "varying vec4 ModelViewPosition;\n"
869 "#endif\n"
870 "\n"
871 "#ifdef MODE_LIGHTSOURCE\n"
872 "uniform vec3 LightPosition;\n"
873 "#endif\n"
874 "uniform vec3 EyePosition;\n"
875 "#ifdef MODE_LIGHTDIRECTION\n"
876 "uniform vec3 LightDir;\n"
877 "#endif\n"
878 "uniform vec4 FogPlane;\n"
879 "\n"
880 "\n"
881 "\n"
882 "\n"
883 "\n"
884 "// 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"
885 "\n"
886 "// fragment shader specific:\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "\n"
889 "uniform sampler2D Texture_Normal;\n"
890 "uniform sampler2D Texture_Color;\n"
891 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
892 "uniform sampler2D Texture_Gloss;\n"
893 "//#endif\n"
894 "#ifdef USEGLOW\n"
895 "uniform sampler2D Texture_Glow;\n"
896 "#endif\n"
897 "#ifdef USEVERTEXTEXTUREBLEND\n"
898 "uniform sampler2D Texture_SecondaryNormal;\n"
899 "uniform sampler2D Texture_SecondaryColor;\n"
900 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
901 "uniform sampler2D Texture_SecondaryGloss;\n"
902 "//#endif\n"
903 "#ifdef USEGLOW\n"
904 "uniform sampler2D Texture_SecondaryGlow;\n"
905 "#endif\n"
906 "#endif\n"
907 "#ifdef USECOLORMAPPING\n"
908 "uniform sampler2D Texture_Pants;\n"
909 "uniform sampler2D Texture_Shirt;\n"
910 "#endif\n"
911 "#ifdef USEFOG\n"
912 "uniform sampler2D Texture_FogMask;\n"
913 "#endif\n"
914 "#ifdef USELIGHTMAP\n"
915 "uniform sampler2D Texture_Lightmap;\n"
916 "#endif\n"
917 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
918 "uniform sampler2D Texture_Deluxemap;\n"
919 "#endif\n"
920 "#ifdef USEREFLECTION\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "#endif\n"
923 "\n"
924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
925 "uniform sampler2D Texture_ScreenDepth;\n"
926 "uniform sampler2D Texture_ScreenNormalMap;\n"
927 "#endif\n"
928 "#ifdef USEDEFERREDLIGHTMAP\n"
929 "uniform sampler2D Texture_ScreenDiffuse;\n"
930 "uniform sampler2D Texture_ScreenSpecular;\n"
931 "#endif\n"
932 "\n"
933 "uniform myhalf3 Color_Pants;\n"
934 "uniform myhalf3 Color_Shirt;\n"
935 "uniform myhalf3 FogColor;\n"
936 "\n"
937 "#ifdef USEFOG\n"
938 "uniform float FogRangeRecip;\n"
939 "uniform float FogPlaneViewDist;\n"
940 "uniform float FogHeightFade;\n"
941 "float FogVertex(void)\n"
942 "{\n"
943 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
944 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
945 "       float fogfrac;\n"
946 "#ifdef USEFOGOUTSIDE\n"
947 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
948 "#else\n"
949 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
950 "#endif\n"
951 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
952 "}\n"
953 "#endif\n"
954 "\n"
955 "#ifdef USEOFFSETMAPPING\n"
956 "uniform float OffsetMapping_Scale;\n"
957 "vec2 OffsetMapping(vec2 TexCoord)\n"
958 "{\n"
959 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
960 "       // 14 sample relief mapping: linear search and then binary search\n"
961 "       // this basically steps forward a small amount repeatedly until it finds\n"
962 "       // itself inside solid, then jitters forward and back using decreasing\n"
963 "       // amounts to find the impact\n"
964 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
965 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
966 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
967 "       vec3 RT = vec3(TexCoord, 1);\n"
968 "       OffsetVector *= 0.1;\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
976 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
977 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
980 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
981 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
982 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
983 "       return RT.xy;\n"
984 "#else\n"
985 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
986 "       // this basically moves forward the full distance, and then backs up based\n"
987 "       // on height of samples\n"
988 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
989 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
990 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
991 "       TexCoord += OffsetVector;\n"
992 "       OffsetVector *= 0.333;\n"
993 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
994 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
995 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
996 "       return TexCoord;\n"
997 "#endif\n"
998 "}\n"
999 "#endif // USEOFFSETMAPPING\n"
1000 "\n"
1001 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1002 "uniform sampler2D Texture_Attenuation;\n"
1003 "uniform samplerCube Texture_Cube;\n"
1004 "\n"
1005 "#ifdef USESHADOWMAPRECT\n"
1006 "# ifdef USESHADOWSAMPLER\n"
1007 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1008 "# else\n"
1009 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1010 "# endif\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef USESHADOWMAP2D\n"
1014 "# ifdef USESHADOWSAMPLER\n"
1015 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1016 "# else\n"
1017 "uniform sampler2D Texture_ShadowMap2D;\n"
1018 "# endif\n"
1019 "#endif\n"
1020 "\n"
1021 "#ifdef USESHADOWMAPVSDCT\n"
1022 "uniform samplerCube Texture_CubeProjection;\n"
1023 "#endif\n"
1024 "\n"
1025 "#ifdef USESHADOWMAPCUBE\n"
1026 "# ifdef USESHADOWSAMPLER\n"
1027 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1028 "# else\n"
1029 "uniform samplerCube Texture_ShadowMapCube;\n"
1030 "# endif\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1034 "uniform vec2 ShadowMap_TextureScale;\n"
1035 "uniform vec4 ShadowMap_Parameters;\n"
1036 "#endif\n"
1037 "\n"
1038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1039 "# ifndef USESHADOWMAPVSDCT\n"
1040 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1041 "{\n"
1042 "       vec3 adir = abs(dir);\n"
1043 "       vec2 tc;\n"
1044 "       vec2 offset;\n"
1045 "       float ma;\n"
1046 "       if (adir.x > adir.y)\n"
1047 "       {\n"
1048 "               if (adir.x > adir.z) // X\n"
1049 "               {\n"
1050 "                       ma = adir.x;\n"
1051 "                       tc = dir.zy;\n"
1052 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1053 "               }\n"
1054 "               else // Z\n"
1055 "               {\n"
1056 "                       ma = adir.z;\n"
1057 "                       tc = dir.xy;\n"
1058 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1059 "               }\n"
1060 "       }\n"
1061 "       else\n"
1062 "       {\n"
1063 "               if (adir.y > adir.z) // Y\n"
1064 "               {\n"
1065 "                       ma = adir.y;\n"
1066 "                       tc = dir.xz;\n"
1067 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1068 "               }\n"
1069 "               else // Z\n"
1070 "               {\n"
1071 "                       ma = adir.z;\n"
1072 "                       tc = dir.xy;\n"
1073 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1074 "               }\n"
1075 "       }\n"
1076 "\n"
1077 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1078 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1079 "       stc.z += ShadowMap_Parameters.z;\n"
1080 "       return stc;\n"
1081 "}\n"
1082 "# else\n"
1083 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1084 "{\n"
1085 "       vec3 adir = abs(dir);\n"
1086 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1087 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1088 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1089 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1090 "       stc.z += ShadowMap_Parameters.z;\n"
1091 "       return stc;\n"
1092 "}\n"
1093 "# endif\n"
1094 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1095 "\n"
1096 "#ifdef USESHADOWMAPCUBE\n"
1097 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1098 "{\n"
1099 "       vec3 adir = abs(dir);\n"
1100 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1101 "}\n"
1102 "#endif\n"
1103 "\n"
1104 "# ifdef USESHADOWMAPRECT\n"
1105 "float ShadowMapCompare(vec3 dir)\n"
1106 "{\n"
1107 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1108 "       float f;\n"
1109 "#  ifdef USESHADOWSAMPLER\n"
1110 "\n"
1111 "#    ifdef USESHADOWMAPPCF\n"
1112 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1113 "       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"
1114 "#    else\n"
1115 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1116 "#    endif\n"
1117 "\n"
1118 "#  else\n"
1119 "\n"
1120 "#    ifdef USESHADOWMAPPCF\n"
1121 "#      if USESHADOWMAPPCF > 1\n"
1122 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1123 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1124 "       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"
1125 "       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"
1126 "       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"
1127 "       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"
1128 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1129 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1130 "#      else\n"
1131 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1132 "       vec2 offset = fract(shadowmaptc.xy);\n"
1133 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1134 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1135 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1136 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1137 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1138 "#      endif\n"
1139 "#    else\n"
1140 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1141 "#    endif\n"
1142 "\n"
1143 "#  endif\n"
1144 "       return f;\n"
1145 "}\n"
1146 "# endif\n"
1147 "\n"
1148 "# ifdef USESHADOWMAP2D\n"
1149 "float ShadowMapCompare(vec3 dir)\n"
1150 "{\n"
1151 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1152 "       float f;\n"
1153 "\n"
1154 "#  ifdef USESHADOWSAMPLER\n"
1155 "#    ifdef USESHADOWMAPPCF\n"
1156 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1157 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1158 "       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"
1159 "#    else\n"
1160 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1161 "#    endif\n"
1162 "#  else\n"
1163 "#    ifdef USESHADOWMAPPCF\n"
1164 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1165 "#      ifdef GL_ARB_texture_gather\n"
1166 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1167 "#      else\n"
1168 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1169 "#      endif\n"
1170 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1171 "       center *= ShadowMap_TextureScale;\n"
1172 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1173 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1174 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1175 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1176 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1177 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1178 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1179 "#     else\n"
1180 "#      ifdef GL_EXT_gpu_shader4\n"
1181 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1182 "#      else\n"
1183 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1184 "#      endif\n"
1185 "#      if USESHADOWMAPPCF > 1\n"
1186 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1187 "       center *= ShadowMap_TextureScale;\n"
1188 "       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"
1189 "       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"
1190 "       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"
1191 "       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"
1192 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1193 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1194 "#      else\n"
1195 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1196 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1197 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1198 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1199 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1200 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1201 "#      endif\n"
1202 "#     endif\n"
1203 "#    else\n"
1204 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1205 "#    endif\n"
1206 "#  endif\n"
1207 "       return f;\n"
1208 "}\n"
1209 "# endif\n"
1210 "\n"
1211 "# ifdef USESHADOWMAPCUBE\n"
1212 "float ShadowMapCompare(vec3 dir)\n"
1213 "{\n"
1214 "       // apply depth texture cubemap as light filter\n"
1215 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1216 "       float f;\n"
1217 "#  ifdef USESHADOWSAMPLER\n"
1218 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1219 "#  else\n"
1220 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1221 "#  endif\n"
1222 "       return f;\n"
1223 "}\n"
1224 "# endif\n"
1225 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1226 "#endif // FRAGMENT_SHADER\n"
1227 "\n"
1228 "\n"
1229 "\n"
1230 "\n"
1231 "#ifdef MODE_DEFERREDGEOMETRY\n"
1232 "#ifdef VERTEX_SHADER\n"
1233 "uniform mat4 TexMatrix;\n"
1234 "#ifdef USEVERTEXTEXTUREBLEND\n"
1235 "uniform mat4 BackgroundTexMatrix;\n"
1236 "#endif\n"
1237 "uniform mat4 ModelViewMatrix;\n"
1238 "void main(void)\n"
1239 "{\n"
1240 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1241 "#ifdef USEVERTEXTEXTUREBLEND\n"
1242 "       gl_FrontColor = gl_Color;\n"
1243 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1244 "#endif\n"
1245 "\n"
1246 "       // transform unnormalized eye direction into tangent space\n"
1247 "#ifdef USEOFFSETMAPPING\n"
1248 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1249 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1250 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1251 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1252 "#endif\n"
1253 "\n"
1254 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1255 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1256 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1257 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1258 "}\n"
1259 "#endif // VERTEX_SHADER\n"
1260 "\n"
1261 "#ifdef FRAGMENT_SHADER\n"
1262 "void main(void)\n"
1263 "{\n"
1264 "#ifdef USEOFFSETMAPPING\n"
1265 "       // apply offsetmapping\n"
1266 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1267 "#define TexCoord TexCoordOffset\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEALPHAKILL\n"
1271 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1272 "               discard;\n"
1273 "#endif\n"
1274 "\n"
1275 "#ifdef USEVERTEXTEXTUREBLEND\n"
1276 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1277 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1278 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1279 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1280 "#endif\n"
1281 "\n"
1282 "#ifdef USEVERTEXTEXTUREBLEND\n"
1283 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1284 "#else\n"
1285 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1387 "       gl_FrontColor = gl_Color;\n"
1388 "#endif\n"
1389 "       // copy the surface texcoord\n"
1390 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1391 "#ifdef USEVERTEXTEXTUREBLEND\n"
1392 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1393 "#endif\n"
1394 "#ifdef USELIGHTMAP\n"
1395 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1396 "#endif\n"
1397 "\n"
1398 "#ifdef MODE_LIGHTSOURCE\n"
1399 "       // transform vertex position into light attenuation/cubemap space\n"
1400 "       // (-1 to +1 across the light box)\n"
1401 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1402 "\n"
1403 "# ifdef USEDIFFUSE\n"
1404 "       // transform unnormalized light direction into tangent space\n"
1405 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1406 "       //  normalize it per pixel)\n"
1407 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1408 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1409 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1410 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1411 "# endif\n"
1412 "#endif\n"
1413 "\n"
1414 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1415 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1416 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1417 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1418 "#endif\n"
1419 "\n"
1420 "       // transform unnormalized eye direction into tangent space\n"
1421 "#ifdef USEEYEVECTOR\n"
1422 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1423 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1424 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1425 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1426 "#endif\n"
1427 "\n"
1428 "#ifdef USEFOG\n"
1429 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1430 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1431 "#endif\n"
1432 "\n"
1433 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1434 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1435 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1436 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1437 "#endif\n"
1438 "\n"
1439 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1440 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1441 "\n"
1442 "#ifdef USEREFLECTION\n"
1443 "       ModelViewProjectionPosition = gl_Position;\n"
1444 "#endif\n"
1445 "}\n"
1446 "#endif // VERTEX_SHADER\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "\n"
1451 "#ifdef FRAGMENT_SHADER\n"
1452 "#ifdef USEDEFERREDLIGHTMAP\n"
1453 "uniform myhalf2 PixelToScreenTexCoord;\n"
1454 "uniform myhalf3 DeferredMod_Diffuse;\n"
1455 "uniform myhalf3 DeferredMod_Specular;\n"
1456 "#endif\n"
1457 "uniform myhalf3 Color_Ambient;\n"
1458 "uniform myhalf3 Color_Diffuse;\n"
1459 "uniform myhalf3 Color_Specular;\n"
1460 "uniform myhalf SpecularPower;\n"
1461 "#ifdef USEGLOW\n"
1462 "uniform myhalf3 Color_Glow;\n"
1463 "#endif\n"
1464 "uniform myhalf Alpha;\n"
1465 "#ifdef USEREFLECTION\n"
1466 "uniform vec4 DistortScaleRefractReflect;\n"
1467 "uniform vec4 ScreenScaleRefractReflect;\n"
1468 "uniform vec4 ScreenCenterRefractReflect;\n"
1469 "uniform myhalf4 ReflectColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTDIRECTION\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "#ifdef MODE_LIGHTSOURCE\n"
1475 "uniform myhalf3 LightColor;\n"
1476 "#endif\n"
1477 "void main(void)\n"
1478 "{\n"
1479 "#ifdef USEOFFSETMAPPING\n"
1480 "       // apply offsetmapping\n"
1481 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1482 "#define TexCoord TexCoordOffset\n"
1483 "#endif\n"
1484 "\n"
1485 "       // combine the diffuse textures (base, pants, shirt)\n"
1486 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1487 "#ifdef USEALPHAKILL\n"
1488 "       if (color.a < 0.5)\n"
1489 "               discard;\n"
1490 "#endif\n"
1491 "       color.a *= Alpha;\n"
1492 "#ifdef USECOLORMAPPING\n"
1493 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1494 "#endif\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1497 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1498 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1499 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1500 "       color.a = 1.0;\n"
1501 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1502 "#endif\n"
1503 "\n"
1504 "       // get the surface normal\n"
1505 "#ifdef USEVERTEXTEXTUREBLEND\n"
1506 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1507 "#else\n"
1508 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1509 "#endif\n"
1510 "\n"
1511 "       // get the material colors\n"
1512 "       myhalf3 diffusetex = color.rgb;\n"
1513 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1514 "# ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1516 "# else\n"
1517 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1518 "# endif\n"
1519 "#endif\n"
1520 "\n"
1521 "\n"
1522 "\n"
1523 "\n"
1524 "#ifdef MODE_LIGHTSOURCE\n"
1525 "       // light source\n"
1526 "#ifdef USEDIFFUSE\n"
1527 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1528 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1529 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1530 "#ifdef USESPECULAR\n"
1531 "#ifdef USEEXACTSPECULARMATH\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1533 "#else\n"
1534 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1535 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1536 "#endif\n"
1537 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1538 "#endif\n"
1539 "#else\n"
1540 "       color.rgb = diffusetex * Color_Ambient;\n"
1541 "#endif\n"
1542 "       color.rgb *= LightColor;\n"
1543 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1544 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1545 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1546 "#endif\n"
1547 "# ifdef USECUBEFILTER\n"
1548 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1549 "# endif\n"
1550 "#endif // MODE_LIGHTSOURCE\n"
1551 "\n"
1552 "\n"
1553 "\n"
1554 "\n"
1555 "#ifdef MODE_LIGHTDIRECTION\n"
1556 "#define SHADING\n"
1557 "#ifdef USEDIFFUSE\n"
1558 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1559 "#endif\n"
1560 "#define lightcolor LightColor\n"
1561 "#endif // MODE_LIGHTDIRECTION\n"
1562 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1563 "#define SHADING\n"
1564 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1565 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1566 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1567 "       // convert modelspace light vector to tangentspace\n"
1568 "       myhalf3 lightnormal;\n"
1569 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1570 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1571 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1572 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1573 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1574 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1575 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1576 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1577 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1578 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1579 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1580 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1581 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1582 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1583 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1584 "#define SHADING\n"
1585 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1586 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1587 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1588 "#endif\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "#ifdef MODE_LIGHTMAP\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1595 "#endif // MODE_LIGHTMAP\n"
1596 "#ifdef MODE_VERTEXCOLOR\n"
1597 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1598 "#endif // MODE_VERTEXCOLOR\n"
1599 "#ifdef MODE_FLATCOLOR\n"
1600 "       color.rgb = diffusetex * Color_Ambient;\n"
1601 "#endif // MODE_FLATCOLOR\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "\n"
1606 "#ifdef SHADING\n"
1607 "# ifdef USEDIFFUSE\n"
1608 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1609 "#  ifdef USESPECULAR\n"
1610 "#   ifdef USEEXACTSPECULARMATH\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1612 "#   else\n"
1613 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1614 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1615 "#   endif\n"
1616 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1617 "#  else\n"
1618 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1619 "#  endif\n"
1620 "# else\n"
1621 "       color.rgb = diffusetex * Color_Ambient;\n"
1622 "# endif\n"
1623 "#endif\n"
1624 "\n"
1625 "#ifdef USEDEFERREDLIGHTMAP\n"
1626 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1627 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1628 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1629 "#endif\n"
1630 "\n"
1631 "#ifdef USEGLOW\n"
1632 "#ifdef USEVERTEXTEXTUREBLEND\n"
1633 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1634 "#else\n"
1635 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1636 "#endif\n"
1637 "#endif\n"
1638 "\n"
1639 "#ifdef USEFOG\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 "       color.rgb *= myhalf(FogVertex());\n"
1642 "#else\n"
1643 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1644 "#endif\n"
1645 "#endif\n"
1646 "\n"
1647 "       // 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"
1648 "#ifdef USEREFLECTION\n"
1649 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1650 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1651 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1652 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1653 "       // FIXME temporary hack to detect the case that the reflection\n"
1654 "       // gets blackened at edges due to leaving the area that contains actual\n"
1655 "       // content.\n"
1656 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1657 "       // 'appening.\n"
1658 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1659 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1660 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1661 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1662 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1663 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1664 "#endif\n"
1665 "\n"
1666 "       gl_FragColor = vec4(color);\n"
1667 "}\n"
1668 "#endif // FRAGMENT_SHADER\n"
1669 "\n"
1670 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1671 "#endif // !MODE_DEFERREDGEOMETRY\n"
1672 "#endif // !MODE_WATER\n"
1673 "#endif // !MODE_REFRACTION\n"
1674 "#endif // !MODE_BLOOMBLUR\n"
1675 "#endif // !MODE_GENERIC\n"
1676 "#endif // !MODE_POSTPROCESS\n"
1677 "#endif // !MODE_SHOWDEPTH\n"
1678 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1679 ;
1680
1681 /*
1682 =========================================================================================================================================================
1683
1684
1685
1686 =========================================================================================================================================================
1687
1688
1689
1690 =========================================================================================================================================================
1691
1692
1693
1694 =========================================================================================================================================================
1695
1696
1697
1698 =========================================================================================================================================================
1699
1700
1701
1702 =========================================================================================================================================================
1703
1704
1705
1706 =========================================================================================================================================================
1707 */
1708
1709 const char *builtincgshaderstring =
1710 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1711 "// written by Forest 'LordHavoc' Hale\n"
1712 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1713 "\n"
1714 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1715 "# define USEFOG\n"
1716 "#endif\n"
1717 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1718 "#define USELIGHTMAP\n"
1719 "#endif\n"
1720 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1721 "#define USEEYEVECTOR\n"
1722 "#endif\n"
1723 "\n"
1724 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1725 "#ifdef VERTEX_SHADER\n"
1726 "void main\n"
1727 "(\n"
1728 "float4 gl_Vertex : POSITION,\n"
1729 "uniform float4x4 ModelViewProjectionMatrix,\n"
1730 "out float4 gl_Position : POSITION\n"
1731 ")\n"
1732 "{\n"
1733 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1734 "}\n"
1735 "#endif\n"
1736 "#else // !MODE_DEPTH_ORSHADOW\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_SHOWDEPTH\n"
1742 "#ifdef VERTEX_SHADER\n"
1743 "void main\n"
1744 "(\n"
1745 "float4 gl_Vertex : POSITION,\n"
1746 "uniform float4x4 ModelViewProjectionMatrix,\n"
1747 "out float4 gl_Position : POSITION,\n"
1748 "out float4 gl_FrontColor : COLOR0\n"
1749 ")\n"
1750 "{\n"
1751 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1752 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1753 "}\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef FRAGMENT_SHADER\n"
1757 "void main\n"
1758 "(\n"
1759 "float4 gl_FrontColor : COLOR0,\n"
1760 "out float4 gl_FragColor : COLOR\n"
1761 ")\n"
1762 "{\n"
1763 "       gl_FragColor = gl_FrontColor;\n"
1764 "}\n"
1765 "#endif\n"
1766 "#else // !MODE_SHOWDEPTH\n"
1767 "\n"
1768 "\n"
1769 "\n"
1770 "\n"
1771 "#ifdef MODE_POSTPROCESS\n"
1772 "\n"
1773 "#ifdef VERTEX_SHADER\n"
1774 "void main\n"
1775 "(\n"
1776 "float4 gl_Vertex : POSITION,\n"
1777 "uniform float4x4 ModelViewProjectionMatrix,\n"
1778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1780 "out float4 gl_Position : POSITION,\n"
1781 "out float2 TexCoord1 : TEXCOORD0,\n"
1782 "out float2 TexCoord2 : TEXCOORD1\n"
1783 ")\n"
1784 "{\n"
1785 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1786 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1787 "#ifdef USEBLOOM\n"
1788 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1789 "#endif\n"
1790 "}\n"
1791 "#endif\n"
1792 "\n"
1793 "#ifdef FRAGMENT_SHADER\n"
1794 "void main\n"
1795 "(\n"
1796 "float2 TexCoord1 : TEXCOORD0,\n"
1797 "float2 TexCoord2 : TEXCOORD1,\n"
1798 "uniform sampler2D Texture_First,\n"
1799 "#ifdef USEBLOOM\n"
1800 "uniform sampler2D Texture_Second,\n"
1801 "#endif\n"
1802 "#ifdef USEGAMMARAMPS\n"
1803 "uniform sampler2D Texture_GammaRamps,\n"
1804 "#endif\n"
1805 "#ifdef USESATURATION\n"
1806 "uniform float Saturation,\n"
1807 "#endif\n"
1808 "#ifdef USEVIEWTINT\n"
1809 "uniform float4 ViewTintColor,\n"
1810 "#endif\n"
1811 "uniform float4 UserVec1,\n"
1812 "uniform float4 UserVec2,\n"
1813 "uniform float4 UserVec3,\n"
1814 "uniform float4 UserVec4,\n"
1815 "uniform float ClientTime,\n"
1816 "uniform float2 PixelSize,\n"
1817 "out float4 gl_FragColor : COLOR\n"
1818 ")\n"
1819 "{\n"
1820 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1821 "#ifdef USEBLOOM\n"
1822 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1823 "#endif\n"
1824 "#ifdef USEVIEWTINT\n"
1825 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef USEPOSTPROCESSING\n"
1829 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1830 "// 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"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1834 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1835 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1836 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1837 "#endif\n"
1838 "\n"
1839 "#ifdef USESATURATION\n"
1840 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1841 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1842 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1843 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef USEGAMMARAMPS\n"
1847 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1848 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1849 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1850 "#endif\n"
1851 "}\n"
1852 "#endif\n"
1853 "#else // !MODE_POSTPROCESS\n"
1854 "\n"
1855 "\n"
1856 "\n"
1857 "\n"
1858 "#ifdef MODE_GENERIC\n"
1859 "#ifdef VERTEX_SHADER\n"
1860 "void main\n"
1861 "(\n"
1862 "float4 gl_Vertex : POSITION,\n"
1863 "uniform float4x4 ModelViewProjectionMatrix,\n"
1864 "float4 gl_Color : COLOR0,\n"
1865 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1866 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1867 "out float4 gl_Position : POSITION,\n"
1868 "out float4 gl_FrontColor : COLOR,\n"
1869 "out float2 TexCoord1 : TEXCOORD0,\n"
1870 "out float2 TexCoord2 : TEXCOORD1\n"
1871 ")\n"
1872 "{\n"
1873 "       gl_FrontColor = gl_Color;\n"
1874 "#ifdef USEDIFFUSE\n"
1875 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1876 "#endif\n"
1877 "#ifdef USESPECULAR\n"
1878 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1879 "#endif\n"
1880 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1881 "}\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "\n"
1886 "void main\n"
1887 "(\n"
1888 "float4 gl_FrontColor : COLOR,\n"
1889 "float2 TexCoord1 : TEXCOORD0,\n"
1890 "float2 TexCoord2 : TEXCOORD1,\n"
1891 "#ifdef USEDIFFUSE\n"
1892 "uniform sampler2D Texture_First,\n"
1893 "#endif\n"
1894 "#ifdef USESPECULAR\n"
1895 "uniform sampler2D Texture_Second,\n"
1896 "#endif\n"
1897 "out float4 gl_FragColor : COLOR\n"
1898 ")\n"
1899 "{\n"
1900 "       gl_FragColor = gl_FrontColor;\n"
1901 "#ifdef USEDIFFUSE\n"
1902 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1903 "#endif\n"
1904 "\n"
1905 "#ifdef USESPECULAR\n"
1906 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1907 "# ifdef USECOLORMAPPING\n"
1908 "       gl_FragColor *= tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEGLOW\n"
1911 "       gl_FragColor += tex2;\n"
1912 "# endif\n"
1913 "# ifdef USEVERTEXTEXTUREBLEND\n"
1914 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1915 "# endif\n"
1916 "#endif\n"
1917 "}\n"
1918 "#endif\n"
1919 "#else // !MODE_GENERIC\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "\n"
1924 "#ifdef MODE_BLOOMBLUR\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix,\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float2 TexCoord : TEXCOORD0\n"
1933 ")\n"
1934 "{\n"
1935 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1936 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1937 "}\n"
1938 "#endif\n"
1939 "\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1941 "\n"
1942 "void main\n"
1943 "(\n"
1944 "float2 TexCoord : TEXCOORD0,\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "uniform float4 BloomBlur_Parameters,\n"
1947 "out float4 gl_FragColor : COLOR\n"
1948 ")\n"
1949 "{\n"
1950 "       int i;\n"
1951 "       float2 tc = TexCoord;\n"
1952 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1953 "       tc += BloomBlur_Parameters.xy;\n"
1954 "       for (i = 1;i < SAMPLES;i++)\n"
1955 "       {\n"
1956 "               color += tex2D(Texture_First, tc).rgb;\n"
1957 "               tc += BloomBlur_Parameters.xy;\n"
1958 "       }\n"
1959 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1960 "}\n"
1961 "#endif\n"
1962 "#else // !MODE_BLOOMBLUR\n"
1963 "#ifdef MODE_REFRACTION\n"
1964 "#ifdef VERTEX_SHADER\n"
1965 "void main\n"
1966 "(\n"
1967 "float4 gl_Vertex : POSITION,\n"
1968 "uniform float4x4 ModelViewProjectionMatrix,\n"
1969 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1970 "uniform float4x4 TexMatrix,\n"
1971 "uniform float3 EyePosition,\n"
1972 "out float4 gl_Position : POSITION,\n"
1973 "out float2 TexCoord : TEXCOORD0,\n"
1974 "out float3 EyeVector : TEXCOORD1,\n"
1975 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1976 ")\n"
1977 "{\n"
1978 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1979 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1980 "       ModelViewProjectionPosition = gl_Position;\n"
1981 "}\n"
1982 "#endif\n"
1983 "\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1985 "void main\n"
1986 "(\n"
1987 "float2 TexCoord : TEXCOORD0,\n"
1988 "float3 EyeVector : TEXCOORD1,\n"
1989 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1990 "uniform sampler2D Texture_Normal,\n"
1991 "uniform sampler2D Texture_Refraction,\n"
1992 "uniform sampler2D Texture_Reflection,\n"
1993 "uniform float4 DistortScaleRefractReflect,\n"
1994 "uniform float4 ScreenScaleRefractReflect,\n"
1995 "uniform float4 ScreenCenterRefractReflect,\n"
1996 "uniform float4 RefractColor,\n"
1997 "out float4 gl_FragColor : COLOR\n"
1998 ")\n"
1999 "{\n"
2000 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2001 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2002 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2003 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2004 "       // FIXME temporary hack to detect the case that the reflection\n"
2005 "       // gets blackened at edges due to leaving the area that contains actual\n"
2006 "       // content.\n"
2007 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2008 "       // 'appening.\n"
2009 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2010 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2011 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2012 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2013 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2014 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_REFRACTION\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_WATER\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "\n"
2025 "void main\n"
2026 "(\n"
2027 "float4 gl_Vertex : POSITION,\n"
2028 "uniform float4x4 ModelViewProjectionMatrix,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "uniform float4x4 TexMatrix,\n"
2031 "uniform float3 EyePosition,\n"
2032 "out float4 gl_Position : POSITION,\n"
2033 "out float2 TexCoord : TEXCOORD0,\n"
2034 "out float3 EyeVector : TEXCOORD1,\n"
2035 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2036 ")\n"
2037 "{\n"
2038 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2039 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2040 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2041 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2042 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2043 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 "       ModelViewProjectionPosition = gl_Position;\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "void main\n"
2050 "(\n"
2051 "float2 TexCoord : TEXCOORD0,\n"
2052 "float3 EyeVector : TEXCOORD1,\n"
2053 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2054 "uniform sampler2D Texture_Normal,\n"
2055 "uniform sampler2D Texture_Refraction,\n"
2056 "uniform sampler2D Texture_Reflection,\n"
2057 "uniform float4 DistortScaleRefractReflect,\n"
2058 "uniform float4 ScreenScaleRefractReflect,\n"
2059 "uniform float4 ScreenCenterRefractReflect,\n"
2060 "uniform float4 RefractColor,\n"
2061 "uniform float4 ReflectColor,\n"
2062 "uniform float ReflectFactor,\n"
2063 "uniform float ReflectOffset,\n"
2064 "out float4 gl_FragColor : COLOR\n"
2065 ")\n"
2066 "{\n"
2067 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2068 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2069 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2070 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2071 "       // FIXME temporary hack to detect the case that the reflection\n"
2072 "       // gets blackened at edges due to leaving the area that contains actual\n"
2073 "       // content.\n"
2074 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2075 "       // 'appening.\n"
2076 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2077 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2078 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2080 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2081 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2082 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2083 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2084 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2085 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2086 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2087 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2088 "}\n"
2089 "#endif\n"
2090 "#else // !MODE_WATER\n"
2091 "\n"
2092 "\n"
2093 "\n"
2094 "\n"
2095 "// 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"
2096 "\n"
2097 "// fragment shader specific:\n"
2098 "#ifdef FRAGMENT_SHADER\n"
2099 "\n"
2100 "#ifdef USEFOG\n"
2101 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2102 "{\n"
2103 "       float fogfrac;\n"
2104 "#ifdef USEFOGOUTSIDE\n"
2105 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2106 "#else\n"
2107 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2108 "#endif\n"
2109 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2110 "}\n"
2111 "#endif\n"
2112 "\n"
2113 "#ifdef USEOFFSETMAPPING\n"
2114 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2115 "{\n"
2116 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2117 "       // 14 sample relief mapping: linear search and then binary search\n"
2118 "       // this basically steps forward a small amount repeatedly until it finds\n"
2119 "       // itself inside solid, then jitters forward and back using decreasing\n"
2120 "       // amounts to find the impact\n"
2121 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2122 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2123 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2124 "       float3 RT = float3(TexCoord, 1);\n"
2125 "       OffsetVector *= 0.1;\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2133 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2134 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2137 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2138 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2139 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2140 "       return RT.xy;\n"
2141 "#else\n"
2142 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2143 "       // this basically moves forward the full distance, and then backs up based\n"
2144 "       // on height of samples\n"
2145 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2146 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2147 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2148 "       TexCoord += OffsetVector;\n"
2149 "       OffsetVector *= 0.333;\n"
2150 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2151 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2152 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2153 "       return TexCoord;\n"
2154 "#endif\n"
2155 "}\n"
2156 "#endif // USEOFFSETMAPPING\n"
2157 "\n"
2158 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2159 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2160 "# ifndef USESHADOWMAPVSDCT\n"
2161 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2162 "{\n"
2163 "       float3 adir = abs(dir);\n"
2164 "       float2 tc;\n"
2165 "       float2 offset;\n"
2166 "       float ma;\n"
2167 "       if (adir.x > adir.y)\n"
2168 "       {\n"
2169 "               if (adir.x > adir.z) // X\n"
2170 "               {\n"
2171 "                       ma = adir.x;\n"
2172 "                       tc = dir.zy;\n"
2173 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2174 "               }\n"
2175 "               else // Z\n"
2176 "               {\n"
2177 "                       ma = adir.z;\n"
2178 "                       tc = dir.xy;\n"
2179 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2180 "               }\n"
2181 "       }\n"
2182 "       else\n"
2183 "       {\n"
2184 "               if (adir.y > adir.z) // Y\n"
2185 "               {\n"
2186 "                       ma = adir.y;\n"
2187 "                       tc = dir.xz;\n"
2188 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2189 "               }\n"
2190 "               else // Z\n"
2191 "               {\n"
2192 "                       ma = adir.z;\n"
2193 "                       tc = dir.xy;\n"
2194 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2195 "               }\n"
2196 "       }\n"
2197 "\n"
2198 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2199 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2200 "       stc.z += ShadowMap_Parameters.z;\n"
2201 "       return stc;\n"
2202 "}\n"
2203 "# else\n"
2204 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2205 "{\n"
2206 "       float3 adir = abs(dir);\n"
2207 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2208 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2209 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2210 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2211 "       stc.z += ShadowMap_Parameters.z;\n"
2212 "       return stc;\n"
2213 "}\n"
2214 "# endif\n"
2215 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2216 "\n"
2217 "#ifdef USESHADOWMAPCUBE\n"
2218 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2219 "{\n"
2220 "    float3 adir = abs(dir);\n"
2221 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2222 "}\n"
2223 "#endif\n"
2224 "\n"
2225 "# ifdef USESHADOWMAPRECT\n"
2226 "#ifdef USESHADOWMAPVSDCT\n"
2227 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2228 "#else\n"
2229 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2230 "#endif\n"
2231 "{\n"
2232 "#ifdef USESHADOWMAPVSDCT\n"
2233 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2234 "#else\n"
2235 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2236 "#endif\n"
2237 "       float f;\n"
2238 "#  ifdef USESHADOWSAMPLER\n"
2239 "\n"
2240 "#    ifdef USESHADOWMAPPCF\n"
2241 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2242 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2243 "#    else\n"
2244 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2245 "#    endif\n"
2246 "\n"
2247 "#  else\n"
2248 "\n"
2249 "#    ifdef USESHADOWMAPPCF\n"
2250 "#      if USESHADOWMAPPCF > 1\n"
2251 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2252 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2253 "    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"
2254 "    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"
2255 "    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"
2256 "    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"
2257 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2258 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2259 "#      else\n"
2260 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2261 "    float2 offset = frac(shadowmaptc.xy);\n"
2262 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2263 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2264 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2265 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2266 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2267 "#      endif\n"
2268 "#    else\n"
2269 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2270 "#    endif\n"
2271 "\n"
2272 "#  endif\n"
2273 "       return f;\n"
2274 "}\n"
2275 "# endif\n"
2276 "\n"
2277 "# ifdef USESHADOWMAP2D\n"
2278 "#ifdef USESHADOWMAPVSDCT\n"
2279 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2280 "#else\n"
2281 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2282 "#endif\n"
2283 "{\n"
2284 "#ifdef USESHADOWMAPVSDCT\n"
2285 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2286 "#else\n"
2287 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2288 "#endif\n"
2289 "    float f;\n"
2290 "\n"
2291 "#  ifdef USESHADOWSAMPLER\n"
2292 "#    ifdef USESHADOWMAPPCF\n"
2293 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2294 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2295 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2296 "#    else\n"
2297 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2298 "#    endif\n"
2299 "#  else\n"
2300 "#    ifdef USESHADOWMAPPCF\n"
2301 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2302 "#      ifdef GL_ARB_texture_gather\n"
2303 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2304 "#      else\n"
2305 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2306 "#      endif\n"
2307 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2308 "    center *= ShadowMap_TextureScale;\n"
2309 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2310 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2311 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2312 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2313 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2314 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2315 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2316 "#     else\n"
2317 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2318 "#      if USESHADOWMAPPCF > 1\n"
2319 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2320 "    center *= ShadowMap_TextureScale;\n"
2321 "    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"
2322 "    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"
2323 "    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"
2324 "    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"
2325 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2326 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2327 "#      else\n"
2328 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2329 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2330 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2331 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2332 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2333 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2334 "#      endif\n"
2335 "#     endif\n"
2336 "#    else\n"
2337 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2338 "#    endif\n"
2339 "#  endif\n"
2340 "    return f;\n"
2341 "}\n"
2342 "# endif\n"
2343 "\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2346 "{\n"
2347 "    // apply depth texture cubemap as light filter\n"
2348 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2349 "    float f;\n"
2350 "#  ifdef USESHADOWSAMPLER\n"
2351 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2352 "#  else\n"
2353 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#  endif\n"
2355 "    return f;\n"
2356 "}\n"
2357 "# endif\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2366 "void main\n"
2367 "(\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2372 "#endif\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2380 "#endif\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2384 "#endif\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2390 "#endif\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2394 ")\n"
2395 "{\n"
2396 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 "       gl_FrontColor = gl_Color;\n"
2399 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2400 "#endif\n"
2401 "\n"
2402 "       // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2408 "#endif\n"
2409 "\n"
2410 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2414 "}\n"
2415 "#endif // VERTEX_SHADER\n"
2416 "\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "void main\n"
2419 "(\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2428 "#endif\n"
2429 "#ifdef USEVERTEXTEXTUREBLEND\n"
2430 "uniform sampler2D Texture_SecondaryNormal,\n"
2431 "#endif\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "uniform float OffsetMapping_Scale,\n"
2434 "#endif\n"
2435 "uniform half SpecularPower,\n"
2436 "out float4 gl_FragColor : COLOR\n"
2437 ")\n"
2438 "{\n"
2439 "       float2 TexCoord = TexCoordBoth.xy;\n"
2440 "#ifdef USEOFFSETMAPPING\n"
2441 "       // apply offsetmapping\n"
2442 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2443 "#define TexCoord TexCoordOffset\n"
2444 "#endif\n"
2445 "\n"
2446 "#ifdef USEALPHAKILL\n"
2447 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2448 "               discard;\n"
2449 "#endif\n"
2450 "\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2453 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2454 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2455 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2456 "#endif\n"
2457 "\n"
2458 "#ifdef USEVERTEXTEXTUREBLEND\n"
2459 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2460 "#else\n"
2461 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2462 "#endif\n"
2463 "\n"
2464 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2465 "}\n"
2466 "#endif // FRAGMENT_SHADER\n"
2467 "#else // !MODE_DEFERREDGEOMETRY\n"
2468 "\n"
2469 "\n"
2470 "\n"
2471 "\n"
2472 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2473 "#ifdef VERTEX_SHADER\n"
2474 "void main\n"
2475 "(\n"
2476 "float4 gl_Vertex : POSITION,\n"
2477 "uniform float4x4 ModelViewProjectionMatrix,\n"
2478 "uniform float4x4 ModelViewMatrix,\n"
2479 "out float4 gl_Position : POSITION,\n"
2480 "out float4 ModelViewPosition : TEXCOORD0\n"
2481 ")\n"
2482 "{\n"
2483 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2484 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2485 "}\n"
2486 "#endif // VERTEX_SHADER\n"
2487 "\n"
2488 "#ifdef FRAGMENT_SHADER\n"
2489 "void main\n"
2490 "(\n"
2491 "float2 Pixel : WPOS,\n"
2492 "float4 ModelViewPosition : TEXCOORD0,\n"
2493 "uniform float4x4 ViewToLight,\n"
2494 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2495 "uniform float3 LightPosition,\n"
2496 "uniform half2 PixelToScreenTexCoord,\n"
2497 "uniform half3 DeferredColor_Ambient,\n"
2498 "uniform half3 DeferredColor_Diffuse,\n"
2499 "#ifdef USESPECULAR\n"
2500 "uniform half3 DeferredColor_Specular,\n"
2501 "uniform half SpecularPower,\n"
2502 "#endif\n"
2503 "uniform sampler2D Texture_Attenuation,\n"
2504 "uniform sampler2D Texture_ScreenDepth,\n"
2505 "uniform sampler2D Texture_ScreenNormalMap,\n"
2506 "\n"
2507 "#ifdef USESHADOWMAPRECT\n"
2508 "# ifdef USESHADOWSAMPLER\n"
2509 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2510 "# else\n"
2511 "uniform samplerRECT Texture_ShadowMapRect,\n"
2512 "# endif\n"
2513 "#endif\n"
2514 "\n"
2515 "#ifdef USESHADOWMAP2D\n"
2516 "# ifdef USESHADOWSAMPLER\n"
2517 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2518 "# else\n"
2519 "uniform sampler2D Texture_ShadowMap2D,\n"
2520 "# endif\n"
2521 "#endif\n"
2522 "\n"
2523 "#ifdef USESHADOWMAPVSDCT\n"
2524 "uniform samplerCUBE Texture_CubeProjection,\n"
2525 "#endif\n"
2526 "\n"
2527 "#ifdef USESHADOWMAPCUBE\n"
2528 "# ifdef USESHADOWSAMPLER\n"
2529 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2530 "# else\n"
2531 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2532 "# endif\n"
2533 "#endif\n"
2534 "\n"
2535 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2536 "uniform float2 ShadowMap_TextureScale,\n"
2537 "uniform float4 ShadowMap_Parameters,\n"
2538 "#endif\n"
2539 "\n"
2540 "out float4 gl_FragData0 : COLOR0,\n"
2541 "out float4 gl_FragData1 : COLOR1\n"
2542 ")\n"
2543 "{\n"
2544 "       // calculate viewspace pixel position\n"
2545 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2546 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2547 "       float3 position;\n"
2548 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2549 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2550 "       // decode viewspace pixel normal\n"
2551 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2552 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2553 "       // surfacenormal = pixel normal in viewspace\n"
2554 "       // LightVector = pixel to light in viewspace\n"
2555 "       // CubeVector = position in lightspace\n"
2556 "       // eyevector = pixel to view in viewspace\n"
2557 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2558 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2559 "#ifdef USEDIFFUSE\n"
2560 "       // calculate diffuse shading\n"
2561 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2562 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2563 "#endif\n"
2564 "#ifdef USESPECULAR\n"
2565 "       // calculate directional shading\n"
2566 "       float3 eyevector = position * -1.0;\n"
2567 "#  ifdef USEEXACTSPECULARMATH\n"
2568 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2569 "#  else\n"
2570 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2571 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2572 "#  endif\n"
2573 "#endif\n"
2574 "\n"
2575 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2576 "       fade *= ShadowMapCompare(CubeVector,\n"
2577 "# if defined(USESHADOWMAP2D)\n"
2578 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPRECT)\n"
2581 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "# if defined(USESHADOWMAPCUBE)\n"
2584 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2585 "# endif\n"
2586 "\n"
2587 "#ifdef USESHADOWMAPVSDCT\n"
2588 ", Texture_CubeProjection\n"
2589 "#endif\n"
2590 "       );\n"
2591 "#endif\n"
2592 "\n"
2593 "#ifdef USEDIFFUSE\n"
2594 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2595 "#else\n"
2596 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2597 "#endif\n"
2598 "#ifdef USESPECULAR\n"
2599 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2600 "#else\n"
2601 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2602 "#endif\n"
2603 "\n"
2604 "# ifdef USECUBEFILTER\n"
2605 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2606 "       gl_FragData0.rgb *= cubecolor;\n"
2607 "       gl_FragData1.rgb *= cubecolor;\n"
2608 "# endif\n"
2609 "}\n"
2610 "#endif // FRAGMENT_SHADER\n"
2611 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef VERTEX_SHADER\n"
2617 "void main\n"
2618 "(\n"
2619 "float4 gl_Vertex : POSITION,\n"
2620 "uniform float4x4 ModelViewProjectionMatrix,\n"
2621 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2622 "float4 gl_Color : COLOR0,\n"
2623 "#endif\n"
2624 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2625 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2626 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2627 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2628 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2629 "\n"
2630 "uniform float3 EyePosition,\n"
2631 "uniform float4x4 TexMatrix,\n"
2632 "#ifdef USEVERTEXTEXTUREBLEND\n"
2633 "uniform float4x4 BackgroundTexMatrix,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float4x4 ModelToLight,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTSOURCE\n"
2639 "uniform float3 LightPosition,\n"
2640 "#endif\n"
2641 "#ifdef MODE_LIGHTDIRECTION\n"
2642 "uniform float3 LightDir,\n"
2643 "#endif\n"
2644 "uniform float4 FogPlane,\n"
2645 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2646 "uniform float3 LightPosition,\n"
2647 "#endif\n"
2648 "\n"
2649 "out float4 gl_FrontColor : COLOR,\n"
2650 "out float4 TexCoordBoth : TEXCOORD0,\n"
2651 "#ifdef USELIGHTMAP\n"
2652 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2653 "#endif\n"
2654 "#ifdef USEEYEVECTOR\n"
2655 "out float3 EyeVector : TEXCOORD2,\n"
2656 "#endif\n"
2657 "#ifdef USEREFLECTION\n"
2658 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2659 "#endif\n"
2660 "#ifdef USEFOG\n"
2661 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2662 "#endif\n"
2663 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2664 "out float3 LightVector : TEXCOORD5,\n"
2665 "#endif\n"
2666 "#ifdef MODE_LIGHTSOURCE\n"
2667 "out float3 CubeVector : TEXCOORD3,\n"
2668 "#endif\n"
2669 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2670 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2671 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2672 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2673 "#endif\n"
2674 "out float4 gl_Position : POSITION\n"
2675 ")\n"
2676 "{\n"
2677 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2678 "       gl_FrontColor = gl_Color;\n"
2679 "#endif\n"
2680 "       // copy the surface texcoord\n"
2681 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2682 "#ifdef USEVERTEXTEXTUREBLEND\n"
2683 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2684 "#endif\n"
2685 "#ifdef USELIGHTMAP\n"
2686 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2687 "#endif\n"
2688 "\n"
2689 "#ifdef MODE_LIGHTSOURCE\n"
2690 "       // transform vertex position into light attenuation/cubemap space\n"
2691 "       // (-1 to +1 across the light box)\n"
2692 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2693 "\n"
2694 "# ifdef USEDIFFUSE\n"
2695 "       // transform unnormalized light direction into tangent space\n"
2696 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2697 "       //  normalize it per pixel)\n"
2698 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2699 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2700 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2701 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2702 "# endif\n"
2703 "#endif\n"
2704 "\n"
2705 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2706 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2707 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2708 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2709 "#endif\n"
2710 "\n"
2711 "       // transform unnormalized eye direction into tangent space\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2714 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2715 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2716 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2717 "#endif\n"
2718 "\n"
2719 "#ifdef USEFOG\n"
2720 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2721 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2722 "#endif\n"
2723 "\n"
2724 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2725 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2726 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2727 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2728 "#endif\n"
2729 "\n"
2730 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2731 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2732 "\n"
2733 "#ifdef USEREFLECTION\n"
2734 "       ModelViewProjectionPosition = gl_Position;\n"
2735 "#endif\n"
2736 "}\n"
2737 "#endif // VERTEX_SHADER\n"
2738 "\n"
2739 "\n"
2740 "\n"
2741 "\n"
2742 "#ifdef FRAGMENT_SHADER\n"
2743 "void main\n"
2744 "(\n"
2745 "#ifdef USEDEFERREDLIGHTMAP\n"
2746 "float2 Pixel : WPOS,\n"
2747 "#endif\n"
2748 "float4 gl_FrontColor : COLOR,\n"
2749 "float4 TexCoordBoth : TEXCOORD0,\n"
2750 "#ifdef USELIGHTMAP\n"
2751 "float2 TexCoordLightmap : TEXCOORD1,\n"
2752 "#endif\n"
2753 "#ifdef USEEYEVECTOR\n"
2754 "float3 EyeVector : TEXCOORD2,\n"
2755 "#endif\n"
2756 "#ifdef USEREFLECTION\n"
2757 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2758 "#endif\n"
2759 "#ifdef USEFOG\n"
2760 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2761 "#endif\n"
2762 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2763 "float3 LightVector : TEXCOORD5,\n"
2764 "#endif\n"
2765 "#ifdef MODE_LIGHTSOURCE\n"
2766 "float3 CubeVector : TEXCOORD3,\n"
2767 "#endif\n"
2768 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2769 "float4 ModelViewPosition : TEXCOORD0,\n"
2770 "#endif\n"
2771 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2772 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2773 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2774 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2775 "#endif\n"
2776 "\n"
2777 "uniform sampler2D Texture_Normal,\n"
2778 "uniform sampler2D Texture_Color,\n"
2779 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2780 "uniform sampler2D Texture_Gloss,\n"
2781 "#endif\n"
2782 "#ifdef USEGLOW\n"
2783 "uniform sampler2D Texture_Glow,\n"
2784 "#endif\n"
2785 "#ifdef USEVERTEXTEXTUREBLEND\n"
2786 "uniform sampler2D Texture_SecondaryNormal,\n"
2787 "uniform sampler2D Texture_SecondaryColor,\n"
2788 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2789 "uniform sampler2D Texture_SecondaryGloss,\n"
2790 "#endif\n"
2791 "#ifdef USEGLOW\n"
2792 "uniform sampler2D Texture_SecondaryGlow,\n"
2793 "#endif\n"
2794 "#endif\n"
2795 "#ifdef USECOLORMAPPING\n"
2796 "uniform sampler2D Texture_Pants,\n"
2797 "uniform sampler2D Texture_Shirt,\n"
2798 "#endif\n"
2799 "#ifdef USEFOG\n"
2800 "uniform sampler2D Texture_FogMask,\n"
2801 "#endif\n"
2802 "#ifdef USELIGHTMAP\n"
2803 "uniform sampler2D Texture_Lightmap,\n"
2804 "#endif\n"
2805 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2806 "uniform sampler2D Texture_Deluxemap,\n"
2807 "#endif\n"
2808 "#ifdef USEREFLECTION\n"
2809 "uniform sampler2D Texture_Reflection,\n"
2810 "#endif\n"
2811 "\n"
2812 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2813 "uniform sampler2D Texture_ScreenDepth,\n"
2814 "uniform sampler2D Texture_ScreenNormalMap,\n"
2815 "#endif\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform sampler2D Texture_ScreenDiffuse,\n"
2818 "uniform sampler2D Texture_ScreenSpecular,\n"
2819 "#endif\n"
2820 "\n"
2821 "#ifdef USECOLORMAPPING\n"
2822 "uniform half3 Color_Pants,\n"
2823 "uniform half3 Color_Shirt,\n"
2824 "#endif\n"
2825 "#ifdef USEFOG\n"
2826 "uniform float3 FogColor,\n"
2827 "uniform float FogRangeRecip,\n"
2828 "uniform float FogPlaneViewDist,\n"
2829 "uniform float FogHeightFade,\n"
2830 "#endif\n"
2831 "\n"
2832 "#ifdef USEOFFSETMAPPING\n"
2833 "uniform float OffsetMapping_Scale,\n"
2834 "#endif\n"
2835 "\n"
2836 "#ifdef USEDEFERREDLIGHTMAP\n"
2837 "uniform half2 PixelToScreenTexCoord,\n"
2838 "uniform half3 DeferredMod_Diffuse,\n"
2839 "uniform half3 DeferredMod_Specular,\n"
2840 "#endif\n"
2841 "uniform half3 Color_Ambient,\n"
2842 "uniform half3 Color_Diffuse,\n"
2843 "uniform half3 Color_Specular,\n"
2844 "uniform half SpecularPower,\n"
2845 "#ifdef USEGLOW\n"
2846 "uniform half3 Color_Glow,\n"
2847 "#endif\n"
2848 "uniform half Alpha,\n"
2849 "#ifdef USEREFLECTION\n"
2850 "uniform float4 DistortScaleRefractReflect,\n"
2851 "uniform float4 ScreenScaleRefractReflect,\n"
2852 "uniform float4 ScreenCenterRefractReflect,\n"
2853 "uniform half4 ReflectColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTDIRECTION\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "uniform half3 LightColor,\n"
2860 "#endif\n"
2861 "\n"
2862 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2863 "uniform sampler2D Texture_Attenuation,\n"
2864 "uniform samplerCUBE Texture_Cube,\n"
2865 "\n"
2866 "#ifdef USESHADOWMAPRECT\n"
2867 "# ifdef USESHADOWSAMPLER\n"
2868 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2869 "# else\n"
2870 "uniform samplerRECT Texture_ShadowMapRect,\n"
2871 "# endif\n"
2872 "#endif\n"
2873 "\n"
2874 "#ifdef USESHADOWMAP2D\n"
2875 "# ifdef USESHADOWSAMPLER\n"
2876 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2877 "# else\n"
2878 "uniform sampler2D Texture_ShadowMap2D,\n"
2879 "# endif\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef USESHADOWMAPVSDCT\n"
2883 "uniform samplerCUBE Texture_CubeProjection,\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef USESHADOWMAPCUBE\n"
2887 "# ifdef USESHADOWSAMPLER\n"
2888 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2889 "# else\n"
2890 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2891 "# endif\n"
2892 "#endif\n"
2893 "\n"
2894 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2895 "uniform float2 ShadowMap_TextureScale,\n"
2896 "uniform float4 ShadowMap_Parameters,\n"
2897 "#endif\n"
2898 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2899 "\n"
2900 "out float4 gl_FragColor : COLOR\n"
2901 ")\n"
2902 "{\n"
2903 "       float2 TexCoord = TexCoordBoth.xy;\n"
2904 "#ifdef USEVERTEXTEXTUREBLEND\n"
2905 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2906 "#endif\n"
2907 "#ifdef USEOFFSETMAPPING\n"
2908 "       // apply offsetmapping\n"
2909 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2910 "#define TexCoord TexCoordOffset\n"
2911 "#endif\n"
2912 "\n"
2913 "       // combine the diffuse textures (base, pants, shirt)\n"
2914 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2915 "#ifdef USEALPHAKILL\n"
2916 "       if (color.a < 0.5)\n"
2917 "               discard;\n"
2918 "#endif\n"
2919 "       color.a *= Alpha;\n"
2920 "#ifdef USECOLORMAPPING\n"
2921 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2922 "#endif\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2925 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2926 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2927 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2928 "       color.a = 1.0;\n"
2929 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2930 "#endif\n"
2931 "\n"
2932 "       // get the surface normal\n"
2933 "#ifdef USEVERTEXTEXTUREBLEND\n"
2934 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2935 "#else\n"
2936 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2937 "#endif\n"
2938 "\n"
2939 "       // get the material colors\n"
2940 "       half3 diffusetex = color.rgb;\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "# ifdef USEVERTEXTEXTUREBLEND\n"
2943 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2944 "# else\n"
2945 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2946 "# endif\n"
2947 "#endif\n"
2948 "\n"
2949 "\n"
2950 "\n"
2951 "\n"
2952 "#ifdef MODE_LIGHTSOURCE\n"
2953 "       // light source\n"
2954 "#ifdef USEDIFFUSE\n"
2955 "       half3 lightnormal = half3(normalize(LightVector));\n"
2956 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2957 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2958 "#ifdef USESPECULAR\n"
2959 "#ifdef USEEXACTSPECULARMATH\n"
2960 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2961 "#else\n"
2962 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2963 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2964 "#endif\n"
2965 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2966 "#endif\n"
2967 "#else\n"
2968 "       color.rgb = diffusetex * Color_Ambient;\n"
2969 "#endif\n"
2970 "       color.rgb *= LightColor;\n"
2971 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2972 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2973 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2974 "# if defined(USESHADOWMAP2D)\n"
2975 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPRECT)\n"
2978 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "# if defined(USESHADOWMAPCUBE)\n"
2981 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2982 "# endif\n"
2983 "\n"
2984 "#ifdef USESHADOWMAPVSDCT\n"
2985 ", Texture_CubeProjection\n"
2986 "#endif\n"
2987 "       );\n"
2988 "\n"
2989 "#endif\n"
2990 "# ifdef USECUBEFILTER\n"
2991 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2992 "# endif\n"
2993 "#endif // MODE_LIGHTSOURCE\n"
2994 "\n"
2995 "\n"
2996 "\n"
2997 "\n"
2998 "#ifdef MODE_LIGHTDIRECTION\n"
2999 "#define SHADING\n"
3000 "#ifdef USEDIFFUSE\n"
3001 "       half3 lightnormal = half3(normalize(LightVector));\n"
3002 "#endif\n"
3003 "#define lightcolor LightColor\n"
3004 "#endif // MODE_LIGHTDIRECTION\n"
3005 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3006 "#define SHADING\n"
3007 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3008 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3009 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3010 "       // convert modelspace light vector to tangentspace\n"
3011 "       half3 lightnormal;\n"
3012 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3013 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3014 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3015 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3016 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3017 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3018 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3019 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3020 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3021 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3022 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3023 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3024 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3025 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3026 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3027 "#define SHADING\n"
3028 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3029 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3030 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3031 "#endif\n"
3032 "\n"
3033 "\n"
3034 "\n"
3035 "\n"
3036 "#ifdef MODE_LIGHTMAP\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3038 "#endif // MODE_LIGHTMAP\n"
3039 "#ifdef MODE_VERTEXCOLOR\n"
3040 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3041 "#endif // MODE_VERTEXCOLOR\n"
3042 "#ifdef MODE_FLATCOLOR\n"
3043 "       color.rgb = diffusetex * Color_Ambient;\n"
3044 "#endif // MODE_FLATCOLOR\n"
3045 "\n"
3046 "\n"
3047 "\n"
3048 "\n"
3049 "#ifdef SHADING\n"
3050 "# ifdef USEDIFFUSE\n"
3051 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3052 "#  ifdef USESPECULAR\n"
3053 "#   ifdef USEEXACTSPECULARMATH\n"
3054 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3055 "#   else\n"
3056 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3057 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3058 "#   endif\n"
3059 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3060 "#  else\n"
3061 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3062 "#  endif\n"
3063 "# else\n"
3064 "       color.rgb = diffusetex * Color_Ambient;\n"
3065 "# endif\n"
3066 "#endif\n"
3067 "\n"
3068 "#ifdef USEDEFERREDLIGHTMAP\n"
3069 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3070 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3071 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3072 "#endif\n"
3073 "\n"
3074 "#ifdef USEGLOW\n"
3075 "#ifdef USEVERTEXTEXTUREBLEND\n"
3076 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3077 "#else\n"
3078 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3079 "#endif\n"
3080 "#endif\n"
3081 "\n"
3082 "#ifdef USEFOG\n"
3083 "#ifdef MODE_LIGHTSOURCE\n"
3084 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3085 "#else\n"
3086 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3087 "#endif\n"
3088 "#endif\n"
3089 "\n"
3090 "       // 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"
3091 "#ifdef USEREFLECTION\n"
3092 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3093 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3094 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3095 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3096 "       // FIXME temporary hack to detect the case that the reflection\n"
3097 "       // gets blackened at edges due to leaving the area that contains actual\n"
3098 "       // content.\n"
3099 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3100 "       // 'appening.\n"
3101 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3102 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3103 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3104 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3105 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3106 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3107 "#endif\n"
3108 "\n"
3109 "       gl_FragColor = float4(color);\n"
3110 "}\n"
3111 "#endif // FRAGMENT_SHADER\n"
3112 "\n"
3113 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3114 "#endif // !MODE_DEFERREDGEOMETRY\n"
3115 "#endif // !MODE_WATER\n"
3116 "#endif // !MODE_REFRACTION\n"
3117 "#endif // !MODE_BLOOMBLUR\n"
3118 "#endif // !MODE_GENERIC\n"
3119 "#endif // !MODE_POSTPROCESS\n"
3120 "#endif // !MODE_SHOWDEPTH\n"
3121 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3122 ;
3123
3124 //=======================================================================================================================================================
3125
3126 typedef struct shaderpermutationinfo_s
3127 {
3128         const char *pretext;
3129         const char *name;
3130 }
3131 shaderpermutationinfo_t;
3132
3133 typedef struct shadermodeinfo_s
3134 {
3135         const char *vertexfilename;
3136         const char *geometryfilename;
3137         const char *fragmentfilename;
3138         const char *pretext;
3139         const char *name;
3140 }
3141 shadermodeinfo_t;
3142
3143 typedef enum shaderpermutation_e
3144 {
3145         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3146         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3147         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3148         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3149         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3150         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3151         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3152         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3153         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3154         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3155         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3156         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3157         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3158         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3159         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3160         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3161         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3162         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3163         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3164         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3165         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3166         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3167         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3168         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3169         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3170         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3171         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3172         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3173 }
3174 shaderpermutation_t;
3175
3176 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3177 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3178 {
3179         {"#define USEDIFFUSE\n", " diffuse"},
3180         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3181         {"#define USEVIEWTINT\n", " viewtint"},
3182         {"#define USECOLORMAPPING\n", " colormapping"},
3183         {"#define USESATURATION\n", " saturation"},
3184         {"#define USEFOGINSIDE\n", " foginside"},
3185         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3186         {"#define USEGAMMARAMPS\n", " gammaramps"},
3187         {"#define USECUBEFILTER\n", " cubefilter"},
3188         {"#define USEGLOW\n", " glow"},
3189         {"#define USEBLOOM\n", " bloom"},
3190         {"#define USESPECULAR\n", " specular"},
3191         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3192         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3193         {"#define USEREFLECTION\n", " reflection"},
3194         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3195         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3196         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3197         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3198         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3199         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3200         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3201         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3202         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3203         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3204         {"#define USEALPHAKILL\n", " alphakill"},
3205 };
3206
3207 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3208 typedef enum shadermode_e
3209 {
3210         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3211         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3212         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3213         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3214         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3215         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3216         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3217         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3218         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3219         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3220         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3221         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3222         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3223         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3224         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3225         SHADERMODE_COUNT
3226 }
3227 shadermode_t;
3228
3229 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3230 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3231 {
3232         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3233         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3234         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3237         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3244         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3245         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3246         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3247 };
3248
3249 #ifdef SUPPORTCG
3250 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3251 {
3252         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3253         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3254         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3257         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3264         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3265         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3266         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3267 };
3268 #endif
3269
3270 struct r_glsl_permutation_s;
3271 typedef struct r_glsl_permutation_s
3272 {
3273         /// hash lookup data
3274         struct r_glsl_permutation_s *hashnext;
3275         unsigned int mode;
3276         unsigned int permutation;
3277
3278         /// indicates if we have tried compiling this permutation already
3279         qboolean compiled;
3280         /// 0 if compilation failed
3281         int program;
3282         /// locations of detected uniforms in program object, or -1 if not found
3283         int loc_Texture_First;
3284         int loc_Texture_Second;
3285         int loc_Texture_GammaRamps;
3286         int loc_Texture_Normal;
3287         int loc_Texture_Color;
3288         int loc_Texture_Gloss;
3289         int loc_Texture_Glow;
3290         int loc_Texture_SecondaryNormal;
3291         int loc_Texture_SecondaryColor;
3292         int loc_Texture_SecondaryGloss;
3293         int loc_Texture_SecondaryGlow;
3294         int loc_Texture_Pants;
3295         int loc_Texture_Shirt;
3296         int loc_Texture_FogMask;
3297         int loc_Texture_Lightmap;
3298         int loc_Texture_Deluxemap;
3299         int loc_Texture_Attenuation;
3300         int loc_Texture_Cube;
3301         int loc_Texture_Refraction;
3302         int loc_Texture_Reflection;
3303         int loc_Texture_ShadowMapRect;
3304         int loc_Texture_ShadowMapCube;
3305         int loc_Texture_ShadowMap2D;
3306         int loc_Texture_CubeProjection;
3307         int loc_Texture_ScreenDepth;
3308         int loc_Texture_ScreenNormalMap;
3309         int loc_Texture_ScreenDiffuse;
3310         int loc_Texture_ScreenSpecular;
3311         int loc_Alpha;
3312         int loc_BloomBlur_Parameters;
3313         int loc_ClientTime;
3314         int loc_Color_Ambient;
3315         int loc_Color_Diffuse;
3316         int loc_Color_Specular;
3317         int loc_Color_Glow;
3318         int loc_Color_Pants;
3319         int loc_Color_Shirt;
3320         int loc_DeferredColor_Ambient;
3321         int loc_DeferredColor_Diffuse;
3322         int loc_DeferredColor_Specular;
3323         int loc_DeferredMod_Diffuse;
3324         int loc_DeferredMod_Specular;
3325         int loc_DistortScaleRefractReflect;
3326         int loc_EyePosition;
3327         int loc_FogColor;
3328         int loc_FogHeightFade;
3329         int loc_FogPlane;
3330         int loc_FogPlaneViewDist;
3331         int loc_FogRangeRecip;
3332         int loc_LightColor;
3333         int loc_LightDir;
3334         int loc_LightPosition;
3335         int loc_OffsetMapping_Scale;
3336         int loc_PixelSize;
3337         int loc_ReflectColor;
3338         int loc_ReflectFactor;
3339         int loc_ReflectOffset;
3340         int loc_RefractColor;
3341         int loc_Saturation;
3342         int loc_ScreenCenterRefractReflect;
3343         int loc_ScreenScaleRefractReflect;
3344         int loc_ScreenToDepth;
3345         int loc_ShadowMap_Parameters;
3346         int loc_ShadowMap_TextureScale;
3347         int loc_SpecularPower;
3348         int loc_UserVec1;
3349         int loc_UserVec2;
3350         int loc_UserVec3;
3351         int loc_UserVec4;
3352         int loc_ViewTintColor;
3353         int loc_ViewToLight;
3354         int loc_ModelToLight;
3355         int loc_TexMatrix;
3356         int loc_BackgroundTexMatrix;
3357         int loc_ModelViewProjectionMatrix;
3358         int loc_ModelViewMatrix;
3359         int loc_PixelToScreenTexCoord;
3360 }
3361 r_glsl_permutation_t;
3362
3363 #define SHADERPERMUTATION_HASHSIZE 256
3364
3365 /// information about each possible shader permutation
3366 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3367 /// currently selected permutation
3368 r_glsl_permutation_t *r_glsl_permutation;
3369 /// storage for permutations linked in the hash table
3370 memexpandablearray_t r_glsl_permutationarray;
3371
3372 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3373 {
3374         //unsigned int hashdepth = 0;
3375         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3376         r_glsl_permutation_t *p;
3377         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3378         {
3379                 if (p->mode == mode && p->permutation == permutation)
3380                 {
3381                         //if (hashdepth > 10)
3382                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3383                         return p;
3384                 }
3385                 //hashdepth++;
3386         }
3387         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3388         p->mode = mode;
3389         p->permutation = permutation;
3390         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3391         r_glsl_permutationhash[mode][hashindex] = p;
3392         //if (hashdepth > 10)
3393         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3394         return p;
3395 }
3396
3397 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3398 {
3399         char *shaderstring;
3400         if (!filename || !filename[0])
3401                 return NULL;
3402         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3403         if (shaderstring)
3404         {
3405                 if (printfromdisknotice)
3406                         Con_DPrintf("from disk %s... ", filename);
3407                 return shaderstring;
3408         }
3409         else if (!strcmp(filename, "glsl/default.glsl"))
3410         {
3411                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3412                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3413         }
3414         return shaderstring;
3415 }
3416
3417 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3418 {
3419         int i;
3420         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3421         int vertstrings_count = 0;
3422         int geomstrings_count = 0;
3423         int fragstrings_count = 0;
3424         char *vertexstring, *geometrystring, *fragmentstring;
3425         const char *vertstrings_list[32+3];
3426         const char *geomstrings_list[32+3];
3427         const char *fragstrings_list[32+3];
3428         char permutationname[256];
3429
3430         if (p->compiled)
3431                 return;
3432         p->compiled = true;
3433         p->program = 0;
3434
3435         permutationname[0] = 0;
3436         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3437         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3438         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3439
3440         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3441
3442         // the first pretext is which type of shader to compile as
3443         // (later these will all be bound together as a program object)
3444         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3445         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3446         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3447
3448         // the second pretext is the mode (for example a light source)
3449         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3450         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3451         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3452         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3453
3454         // now add all the permutation pretexts
3455         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3456         {
3457                 if (permutation & (1<<i))
3458                 {
3459                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3460                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3461                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3462                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3463                 }
3464                 else
3465                 {
3466                         // keep line numbers correct
3467                         vertstrings_list[vertstrings_count++] = "\n";
3468                         geomstrings_list[geomstrings_count++] = "\n";
3469                         fragstrings_list[fragstrings_count++] = "\n";
3470                 }
3471         }
3472
3473         // now append the shader text itself
3474         vertstrings_list[vertstrings_count++] = vertexstring;
3475         geomstrings_list[geomstrings_count++] = geometrystring;
3476         fragstrings_list[fragstrings_count++] = fragmentstring;
3477
3478         // if any sources were NULL, clear the respective list
3479         if (!vertexstring)
3480                 vertstrings_count = 0;
3481         if (!geometrystring)
3482                 geomstrings_count = 0;
3483         if (!fragmentstring)
3484                 fragstrings_count = 0;
3485
3486         // compile the shader program
3487         if (vertstrings_count + geomstrings_count + fragstrings_count)
3488                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3489         if (p->program)
3490         {
3491                 CHECKGLERROR
3492                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3493                 // look up all the uniform variable names we care about, so we don't
3494                 // have to look them up every time we set them
3495
3496                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3497                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3498                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3499                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3500                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3501                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3502                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3503                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3504                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3505                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3506                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3507                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3508                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3509                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3510                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3511                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3512                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3513                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3514                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3515                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3516                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3517                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3518                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3519                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3520                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3521                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3522                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3523                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3524                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3525                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3526                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3527                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3528                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3529                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3530                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3531                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3532                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3533                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3534                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3535                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3536                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3537                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3538                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3539                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3540                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3541                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3542                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3543                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3544                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3545                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3546                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3547                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3548                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3549                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3550                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3551                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3552                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3553                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3554                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3555                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3556                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3557                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3558                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3559                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3560                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3561                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3562                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3563                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3564                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3565                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3566                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3567                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3568                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3569                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3570                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3571                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3572                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3573                 // initialize the samplers to refer to the texture units we use
3574                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3575                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3576                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3577                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3578                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3579                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3580                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3581                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3582                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3583                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3584                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3585                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3586                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3587                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3588                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3589                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3590                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3591                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3592                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3593                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3594                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3595                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3596                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3597                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3598                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3599                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3600                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3601                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3602                 CHECKGLERROR
3603                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3604         }
3605         else
3606                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3607
3608         // free the strings
3609         if (vertexstring)
3610                 Mem_Free(vertexstring);
3611         if (geometrystring)
3612                 Mem_Free(geometrystring);
3613         if (fragmentstring)
3614                 Mem_Free(fragmentstring);
3615 }
3616
3617 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3618 {
3619         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3620         if (r_glsl_permutation != perm)
3621         {
3622                 r_glsl_permutation = perm;
3623                 if (!r_glsl_permutation->program)
3624                 {
3625                         if (!r_glsl_permutation->compiled)
3626                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3627                         if (!r_glsl_permutation->program)
3628                         {
3629                                 // remove features until we find a valid permutation
3630                                 int i;
3631                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3632                                 {
3633                                         // reduce i more quickly whenever it would not remove any bits
3634                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3635                                         if (!(permutation & j))
3636                                                 continue;
3637                                         permutation -= j;
3638                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3639                                         if (!r_glsl_permutation->compiled)
3640                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3641                                         if (r_glsl_permutation->program)
3642                                                 break;
3643                                 }
3644                                 if (i >= SHADERPERMUTATION_COUNT)
3645                                 {
3646                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3647                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3648                                         qglUseProgramObjectARB(0);CHECKGLERROR
3649                                         return; // no bit left to clear, entire mode is broken
3650                                 }
3651                         }
3652                 }
3653                 CHECKGLERROR
3654                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3655         }
3656         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3657         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3658 }
3659
3660 #ifdef SUPPORTCG
3661 #include <Cg/cgGL.h>
3662 struct r_cg_permutation_s;
3663 typedef struct r_cg_permutation_s
3664 {
3665         /// hash lookup data
3666         struct r_cg_permutation_s *hashnext;
3667         unsigned int mode;
3668         unsigned int permutation;
3669
3670         /// indicates if we have tried compiling this permutation already
3671         qboolean compiled;
3672         /// 0 if compilation failed
3673         CGprogram vprogram;
3674         CGprogram fprogram;
3675         /// locations of detected parameters in programs, or NULL if not found
3676         CGparameter vp_EyePosition;
3677         CGparameter vp_FogPlane;
3678         CGparameter vp_LightDir;
3679         CGparameter vp_LightPosition;
3680         CGparameter vp_ModelToLight;
3681         CGparameter vp_TexMatrix;
3682         CGparameter vp_BackgroundTexMatrix;
3683         CGparameter vp_ModelViewProjectionMatrix;
3684         CGparameter vp_ModelViewMatrix;
3685
3686         CGparameter fp_Texture_First;
3687         CGparameter fp_Texture_Second;
3688         CGparameter fp_Texture_GammaRamps;
3689         CGparameter fp_Texture_Normal;
3690         CGparameter fp_Texture_Color;
3691         CGparameter fp_Texture_Gloss;
3692         CGparameter fp_Texture_Glow;
3693         CGparameter fp_Texture_SecondaryNormal;
3694         CGparameter fp_Texture_SecondaryColor;
3695         CGparameter fp_Texture_SecondaryGloss;
3696         CGparameter fp_Texture_SecondaryGlow;
3697         CGparameter fp_Texture_Pants;
3698         CGparameter fp_Texture_Shirt;
3699         CGparameter fp_Texture_FogMask;
3700         CGparameter fp_Texture_Lightmap;
3701         CGparameter fp_Texture_Deluxemap;
3702         CGparameter fp_Texture_Attenuation;
3703         CGparameter fp_Texture_Cube;
3704         CGparameter fp_Texture_Refraction;
3705         CGparameter fp_Texture_Reflection;
3706         CGparameter fp_Texture_ShadowMapRect;
3707         CGparameter fp_Texture_ShadowMapCube;
3708         CGparameter fp_Texture_ShadowMap2D;
3709         CGparameter fp_Texture_CubeProjection;
3710         CGparameter fp_Texture_ScreenDepth;
3711         CGparameter fp_Texture_ScreenNormalMap;
3712         CGparameter fp_Texture_ScreenDiffuse;
3713         CGparameter fp_Texture_ScreenSpecular;
3714         CGparameter fp_Alpha;
3715         CGparameter fp_BloomBlur_Parameters;
3716         CGparameter fp_ClientTime;
3717         CGparameter fp_Color_Ambient;
3718         CGparameter fp_Color_Diffuse;
3719         CGparameter fp_Color_Specular;
3720         CGparameter fp_Color_Glow;
3721         CGparameter fp_Color_Pants;
3722         CGparameter fp_Color_Shirt;
3723         CGparameter fp_DeferredColor_Ambient;
3724         CGparameter fp_DeferredColor_Diffuse;
3725         CGparameter fp_DeferredColor_Specular;
3726         CGparameter fp_DeferredMod_Diffuse;
3727         CGparameter fp_DeferredMod_Specular;
3728         CGparameter fp_DistortScaleRefractReflect;
3729         CGparameter fp_EyePosition;
3730         CGparameter fp_FogColor;
3731         CGparameter fp_FogHeightFade;
3732         CGparameter fp_FogPlane;
3733         CGparameter fp_FogPlaneViewDist;
3734         CGparameter fp_FogRangeRecip;
3735         CGparameter fp_LightColor;
3736         CGparameter fp_LightDir;
3737         CGparameter fp_LightPosition;
3738         CGparameter fp_OffsetMapping_Scale;
3739         CGparameter fp_PixelSize;
3740         CGparameter fp_ReflectColor;
3741         CGparameter fp_ReflectFactor;
3742         CGparameter fp_ReflectOffset;
3743         CGparameter fp_RefractColor;
3744         CGparameter fp_Saturation;
3745         CGparameter fp_ScreenCenterRefractReflect;
3746         CGparameter fp_ScreenScaleRefractReflect;
3747         CGparameter fp_ScreenToDepth;
3748         CGparameter fp_ShadowMap_Parameters;
3749         CGparameter fp_ShadowMap_TextureScale;
3750         CGparameter fp_SpecularPower;
3751         CGparameter fp_UserVec1;
3752         CGparameter fp_UserVec2;
3753         CGparameter fp_UserVec3;
3754         CGparameter fp_UserVec4;
3755         CGparameter fp_ViewTintColor;
3756         CGparameter fp_ViewToLight;
3757         CGparameter fp_PixelToScreenTexCoord;
3758 }
3759 r_cg_permutation_t;
3760
3761 /// information about each possible shader permutation
3762 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3763 /// currently selected permutation
3764 r_cg_permutation_t *r_cg_permutation;
3765 /// storage for permutations linked in the hash table
3766 memexpandablearray_t r_cg_permutationarray;
3767
3768 #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));}}
3769
3770 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3771 {
3772         //unsigned int hashdepth = 0;
3773         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3774         r_cg_permutation_t *p;
3775         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3776         {
3777                 if (p->mode == mode && p->permutation == permutation)
3778                 {
3779                         //if (hashdepth > 10)
3780                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3781                         return p;
3782                 }
3783                 //hashdepth++;
3784         }
3785         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3786         p->mode = mode;
3787         p->permutation = permutation;
3788         p->hashnext = r_cg_permutationhash[mode][hashindex];
3789         r_cg_permutationhash[mode][hashindex] = p;
3790         //if (hashdepth > 10)
3791         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3792         return p;
3793 }
3794
3795 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3796 {
3797         char *shaderstring;
3798         if (!filename || !filename[0])
3799                 return NULL;
3800         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3801         if (shaderstring)
3802         {
3803                 if (printfromdisknotice)
3804                         Con_DPrintf("from disk %s... ", filename);
3805                 return shaderstring;
3806         }
3807         else if (!strcmp(filename, "cg/default.cg"))
3808         {
3809                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3810                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3811         }
3812         return shaderstring;
3813 }
3814
3815 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3816 {
3817         int i;
3818         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3819         int vertstrings_count = 0, vertstring_length = 0;
3820         int geomstrings_count = 0, geomstring_length = 0;
3821         int fragstrings_count = 0, fragstring_length = 0;
3822         char *t;
3823         char *vertexstring, *geometrystring, *fragmentstring;
3824         char *vertstring, *geomstring, *fragstring;
3825         const char *vertstrings_list[32+3];
3826         const char *geomstrings_list[32+3];
3827         const char *fragstrings_list[32+3];
3828         char permutationname[256];
3829         CGprofile vertexProfile;
3830         CGprofile fragmentProfile;
3831
3832         if (p->compiled)
3833                 return;
3834         p->compiled = true;
3835         p->vprogram = NULL;
3836         p->fprogram = NULL;
3837
3838         permutationname[0] = 0;
3839         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3840         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3841         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3842
3843         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3844
3845         // the first pretext is which type of shader to compile as
3846         // (later these will all be bound together as a program object)
3847         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3848         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3849         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3850
3851         // the second pretext is the mode (for example a light source)
3852         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3853         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3854         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3855         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3856
3857         // now add all the permutation pretexts
3858         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3859         {
3860                 if (permutation & (1<<i))
3861                 {
3862                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3863                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3864                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3865                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3866                 }
3867                 else
3868                 {
3869                         // keep line numbers correct
3870                         vertstrings_list[vertstrings_count++] = "\n";
3871                         geomstrings_list[geomstrings_count++] = "\n";
3872                         fragstrings_list[fragstrings_count++] = "\n";
3873                 }
3874         }
3875
3876         // now append the shader text itself
3877         vertstrings_list[vertstrings_count++] = vertexstring;
3878         geomstrings_list[geomstrings_count++] = geometrystring;
3879         fragstrings_list[fragstrings_count++] = fragmentstring;
3880
3881         // if any sources were NULL, clear the respective list
3882         if (!vertexstring)
3883                 vertstrings_count = 0;
3884         if (!geometrystring)
3885                 geomstrings_count = 0;
3886         if (!fragmentstring)
3887                 fragstrings_count = 0;
3888
3889         vertstring_length = 0;
3890         for (i = 0;i < vertstrings_count;i++)
3891                 vertstring_length += strlen(vertstrings_list[i]);
3892         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3893         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3894                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3895
3896         geomstring_length = 0;
3897         for (i = 0;i < geomstrings_count;i++)
3898                 geomstring_length += strlen(geomstrings_list[i]);
3899         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3900         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3901                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3902
3903         fragstring_length = 0;
3904         for (i = 0;i < fragstrings_count;i++)
3905                 fragstring_length += strlen(fragstrings_list[i]);
3906         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3907         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3908                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3909
3910         CHECKGLERROR
3911         CHECKCGERROR
3912         //vertexProfile = CG_PROFILE_ARBVP1;
3913         //fragmentProfile = CG_PROFILE_ARBFP1;
3914         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3915         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3916         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3917         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3918         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3919         CHECKGLERROR
3920
3921         // compile the vertex program
3922         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3923         {
3924                 CHECKCGERROR
3925 #if 0
3926                 cgCompileProgram(p->vprogram);CHECKCGERROR
3927                 if (!cgIsProgramCompiled(p->vprogram))
3928                 {
3929                         CHECKCGERROR
3930                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3931                         p->vprogram = 0;
3932                 }
3933                 else
3934 #endif
3935                 {
3936                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3937                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3938                         // look up all the uniform variable names we care about, so we don't
3939                         // have to look them up every time we set them
3940                         CHECKCGERROR
3941                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3942                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3943                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3944                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3945                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3946                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3947                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3948                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3949                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3950                         CHECKCGERROR
3951                 }
3952         }
3953
3954         // compile the fragment program
3955         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3956         {
3957 #if 0
3958                 cgCompileProgram(p->fprogram);CHECKCGERROR
3959                 if (!cgIsProgramCompiled(p->fprogram))
3960                 {
3961                         CHECKCGERROR
3962                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3963                         p->fprogram = 0;
3964                 }
3965                 else
3966 #endif
3967                 {
3968                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3969                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3970                         CHECKCGERROR
3971                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3972                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3973                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3974                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3975                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3976                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3977                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3978                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3979                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3980                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3981                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3982                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3983                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3984                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3985                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3986                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3987                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3988                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3989                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3990                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3991                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3992                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3993                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3994                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3995                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3996                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3997                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3998                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3999                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4000                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4001                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4002                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4003                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4004                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4005                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4006                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4007                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4008                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4009                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4010                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4011                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4012                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4013                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4014                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4015                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4016                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4017                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4018                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4019                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4020                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4021                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4022                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4023                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4024                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4025                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4026                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4027                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4028                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4029                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4030                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4031                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4032                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4033                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4034                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4035                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4036                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4037                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4038                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4039                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4040                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4041                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4042                         p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4043                         CHECKCGERROR
4044                 }
4045         }
4046
4047         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4048                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4049         else
4050                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4051
4052         // free the strings
4053         if (vertstring)
4054                 Mem_Free(vertstring);
4055         if (geomstring)
4056                 Mem_Free(geomstring);
4057         if (fragstring)
4058                 Mem_Free(fragstring);
4059         if (vertexstring)
4060                 Mem_Free(vertexstring);
4061         if (geometrystring)
4062                 Mem_Free(geometrystring);
4063         if (fragmentstring)
4064                 Mem_Free(fragmentstring);
4065 }
4066
4067 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4068 {
4069         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4070         CHECKGLERROR
4071         CHECKCGERROR
4072         if (r_cg_permutation != perm)
4073         {
4074                 r_cg_permutation = perm;
4075                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4076                 {
4077                         if (!r_cg_permutation->compiled)
4078                                 R_CG_CompilePermutation(perm, mode, permutation);
4079                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4080                         {
4081                                 // remove features until we find a valid permutation
4082                                 int i;
4083                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4084                                 {
4085                                         // reduce i more quickly whenever it would not remove any bits
4086                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4087                                         if (!(permutation & j))
4088                                                 continue;
4089                                         permutation -= j;
4090                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4091                                         if (!r_cg_permutation->compiled)
4092                                                 R_CG_CompilePermutation(perm, mode, permutation);
4093                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4094                                                 break;
4095                                 }
4096                                 if (i >= SHADERPERMUTATION_COUNT)
4097                                 {
4098                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4099                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4100                                         return; // no bit left to clear, entire mode is broken
4101                                 }
4102                         }
4103                 }
4104                 CHECKGLERROR
4105                 CHECKCGERROR
4106                 if (r_cg_permutation->vprogram)
4107                 {
4108                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4109                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4110                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4111                 }
4112                 else
4113                 {
4114                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4115                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4116                 }
4117                 if (r_cg_permutation->fprogram)
4118                 {
4119                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4120                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4121                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4122                 }
4123                 else
4124                 {
4125                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4126                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4127                 }
4128         }
4129         CHECKCGERROR
4130         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4131         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4132 }
4133
4134 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4135 {
4136         cgGLSetTextureParameter(param, R_GetTexture(tex));
4137         cgGLEnableTextureParameter(param);
4138 }
4139 #endif
4140
4141 void R_GLSL_Restart_f(void)
4142 {
4143         unsigned int i, limit;
4144         switch(vid.renderpath)
4145         {
4146         case RENDERPATH_GL20:
4147                 {
4148                         r_glsl_permutation_t *p;
4149                         r_glsl_permutation = NULL;
4150                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4151                         for (i = 0;i < limit;i++)
4152                         {
4153                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4154                                 {
4155                                         GL_Backend_FreeProgram(p->program);
4156                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4157                                 }
4158                         }
4159                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4160                 }
4161                 break;
4162         case RENDERPATH_CGGL:
4163 #ifdef SUPPORTCG
4164                 {
4165                         r_cg_permutation_t *p;
4166                         r_cg_permutation = NULL;
4167                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4168                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4169                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4170                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4171                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4172                         for (i = 0;i < limit;i++)
4173                         {
4174                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4175                                 {
4176                                         if (p->vprogram)
4177                                                 cgDestroyProgram(p->vprogram);
4178                                         if (p->fprogram)
4179                                                 cgDestroyProgram(p->fprogram);
4180                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4181                                 }
4182                         }
4183                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4184                 }
4185                 break;
4186 #endif
4187         case RENDERPATH_GL13:
4188         case RENDERPATH_GL11:
4189                 break;
4190         }
4191 }
4192
4193 void R_GLSL_DumpShader_f(void)
4194 {
4195         int i;
4196         qfile_t *file;
4197
4198         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4199         if (file)
4200         {
4201                 FS_Print(file, "/* The engine may define the following macros:\n");
4202                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4203                 for (i = 0;i < SHADERMODE_COUNT;i++)
4204                         FS_Print(file, glslshadermodeinfo[i].pretext);
4205                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4206                         FS_Print(file, shaderpermutationinfo[i].pretext);
4207                 FS_Print(file, "*/\n");
4208                 FS_Print(file, builtinshaderstring);
4209                 FS_Close(file);
4210                 Con_Printf("glsl/default.glsl written\n");
4211         }
4212         else
4213                 Con_Printf("failed to write to glsl/default.glsl\n");
4214
4215 #ifdef SUPPORTCG
4216         file = FS_OpenRealFile("cg/default.cg", "w", false);
4217         if (file)
4218         {
4219                 FS_Print(file, "/* The engine may define the following macros:\n");
4220                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4221                 for (i = 0;i < SHADERMODE_COUNT;i++)
4222                         FS_Print(file, cgshadermodeinfo[i].pretext);
4223                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4224                         FS_Print(file, shaderpermutationinfo[i].pretext);
4225                 FS_Print(file, "*/\n");
4226                 FS_Print(file, builtincgshaderstring);
4227                 FS_Close(file);
4228                 Con_Printf("cg/default.cg written\n");
4229         }
4230         else
4231                 Con_Printf("failed to write to cg/default.cg\n");
4232 #endif
4233 }
4234
4235 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4236 {
4237         if (!second)
4238                 texturemode = GL_MODULATE;
4239         switch (vid.renderpath)
4240         {
4241         case RENDERPATH_GL20:
4242                 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))));
4243                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4244                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4245                 break;
4246         case RENDERPATH_CGGL:
4247 #ifdef SUPPORTCG
4248                 CHECKCGERROR
4249                 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))));
4250                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4251                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4252 #endif
4253                 break;
4254         case RENDERPATH_GL13:
4255                 R_Mesh_TexBind(0, first );
4256                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4257                 R_Mesh_TexBind(1, second);
4258                 if (second)
4259                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4260                 break;
4261         case RENDERPATH_GL11:
4262                 R_Mesh_TexBind(0, first );
4263                 break;
4264         }
4265 }
4266
4267 void R_SetupShader_DepthOrShadow(void)
4268 {
4269         switch (vid.renderpath)
4270         {
4271         case RENDERPATH_GL20:
4272                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4273                 break;
4274         case RENDERPATH_CGGL:
4275 #ifdef SUPPORTCG
4276                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4277 #endif
4278                 break;
4279         case RENDERPATH_GL13:
4280                 R_Mesh_TexBind(0, 0);
4281                 R_Mesh_TexBind(1, 0);
4282                 break;
4283         case RENDERPATH_GL11:
4284                 R_Mesh_TexBind(0, 0);
4285                 break;
4286         }
4287 }
4288
4289 void R_SetupShader_ShowDepth(void)
4290 {
4291         switch (vid.renderpath)
4292         {
4293         case RENDERPATH_GL20:
4294                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4295                 break;
4296         case RENDERPATH_CGGL:
4297 #ifdef SUPPORTCG
4298                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4299 #endif
4300                 break;
4301         case RENDERPATH_GL13:
4302                 break;
4303         case RENDERPATH_GL11:
4304                 break;
4305         }
4306 }
4307
4308 extern qboolean r_shadow_usingdeferredprepass;
4309 extern cvar_t r_shadow_deferred_8bitrange;
4310 extern rtexture_t *r_shadow_attenuationgradienttexture;
4311 extern rtexture_t *r_shadow_attenuation2dtexture;
4312 extern rtexture_t *r_shadow_attenuation3dtexture;
4313 extern qboolean r_shadow_usingshadowmaprect;
4314 extern qboolean r_shadow_usingshadowmapcube;
4315 extern qboolean r_shadow_usingshadowmap2d;
4316 extern float r_shadow_shadowmap_texturescale[2];
4317 extern float r_shadow_shadowmap_parameters[4];
4318 extern qboolean r_shadow_shadowmapvsdct;
4319 extern qboolean r_shadow_shadowmapsampler;
4320 extern int r_shadow_shadowmappcf;
4321 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4322 extern rtexture_t *r_shadow_shadowmap2dtexture;
4323 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4324 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4325 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4326 extern int r_shadow_prepass_width;
4327 extern int r_shadow_prepass_height;
4328 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4329 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4330 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4331 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4332 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4333 {
4334         // select a permutation of the lighting shader appropriate to this
4335         // combination of texture, entity, light source, and fogging, only use the
4336         // minimum features necessary to avoid wasting rendering time in the
4337         // fragment shader on features that are not being used
4338         unsigned int permutation = 0;
4339         unsigned int mode = 0;
4340         float m16f[16];
4341         if (rsurfacepass == RSURFPASS_BACKGROUND)
4342         {
4343                 // distorted background
4344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4345                         mode = SHADERMODE_WATER;
4346                 else
4347                         mode = SHADERMODE_REFRACTION;
4348                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4349                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4350                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4351                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4352                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4353                 R_Mesh_ColorPointer(NULL, 0, 0);
4354                 GL_AlphaTest(false);
4355                 GL_BlendFunc(GL_ONE, GL_ZERO);
4356         }
4357         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4358         {
4359                 if (r_glsl_offsetmapping.integer)
4360                 {
4361                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4362                         if (r_glsl_offsetmapping_reliefmapping.integer)
4363                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4364                 }
4365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4366                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4368                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4369                 // normalmap (deferred prepass), may use alpha test on diffuse
4370                 mode = SHADERMODE_DEFERREDGEOMETRY;
4371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4372                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4373                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4374                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4375                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4376                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4377                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4378                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4379                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4380                 else
4381                         R_Mesh_ColorPointer(NULL, 0, 0);
4382                 GL_AlphaTest(false);
4383                 GL_BlendFunc(GL_ONE, GL_ZERO);
4384         }
4385         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4386         {
4387                 if (r_glsl_offsetmapping.integer)
4388                 {
4389                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4390                         if (r_glsl_offsetmapping_reliefmapping.integer)
4391                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4392                 }
4393                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4394                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4395                 // light source
4396                 mode = SHADERMODE_LIGHTSOURCE;
4397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4398                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4399                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4400                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4401                 if (diffusescale > 0)
4402                         permutation |= SHADERPERMUTATION_DIFFUSE;
4403                 if (specularscale > 0)
4404                 {
4405                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4406                         if (r_shadow_glossexact.integer)
4407                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4408                 }
4409                 if (r_refdef.fogenabled)
4410                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4411                 if (rsurface.texture->colormapping)
4412                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4413                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4414                 {
4415                         if (r_shadow_usingshadowmaprect)
4416                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4417                         if (r_shadow_usingshadowmap2d)
4418                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4419                         if (r_shadow_usingshadowmapcube)
4420                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4421                         else if(r_shadow_shadowmapvsdct)
4422                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4423
4424                         if (r_shadow_shadowmapsampler)
4425                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4426                         if (r_shadow_shadowmappcf > 1)
4427                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4428                         else if (r_shadow_shadowmappcf)
4429                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4430                 }
4431                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4432                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4433                 {
4434                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4435                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4436                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4437                 }
4438                 else
4439                 {
4440                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4441                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4442                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4443                 }
4444                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4445                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4446                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4447                 else
4448                         R_Mesh_ColorPointer(NULL, 0, 0);
4449                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4450                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4451         }
4452         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4453         {
4454                 if (r_glsl_offsetmapping.integer)
4455                 {
4456                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457                         if (r_glsl_offsetmapping_reliefmapping.integer)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4459                 }
4460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462                 // unshaded geometry (fullbright or ambient model lighting)
4463                 mode = SHADERMODE_FLATCOLOR;
4464                 ambientscale = diffusescale = specularscale = 0;
4465                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4466                         permutation |= SHADERPERMUTATION_GLOW;
4467                 if (r_refdef.fogenabled)
4468                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4469                 if (rsurface.texture->colormapping)
4470                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4471                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4472                         permutation |= SHADERPERMUTATION_REFLECTION;
4473                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4474                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4475                 {
4476                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4477                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4478                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4479                 }
4480                 else
4481                 {
4482                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4483                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4484                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4485                 }
4486                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4487                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4488                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4489                 else
4490                         R_Mesh_ColorPointer(NULL, 0, 0);
4491                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4492                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4493         }
4494         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4495         {
4496                 if (r_glsl_offsetmapping.integer)
4497                 {
4498                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4499                         if (r_glsl_offsetmapping_reliefmapping.integer)
4500                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4501                 }
4502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4503                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4504                 // directional model lighting
4505                 mode = SHADERMODE_LIGHTDIRECTION;
4506                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4507                         permutation |= SHADERPERMUTATION_GLOW;
4508                 permutation |= SHADERPERMUTATION_DIFFUSE;
4509                 if (specularscale > 0)
4510                 {
4511                         permutation |= SHADERPERMUTATION_SPECULAR;
4512                         if (r_shadow_glossexact.integer)
4513                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4514                 }
4515                 if (r_refdef.fogenabled)
4516                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4517                 if (rsurface.texture->colormapping)
4518                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4520                         permutation |= SHADERPERMUTATION_REFLECTION;
4521                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4522                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4523                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4524                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4525                 {
4526                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4527                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4528                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4529                 }
4530                 else
4531                 {
4532                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4533                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4534                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4535                 }
4536                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4537                 R_Mesh_ColorPointer(NULL, 0, 0);
4538                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4539                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4540         }
4541         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4542         {
4543                 if (r_glsl_offsetmapping.integer)
4544                 {
4545                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4546                         if (r_glsl_offsetmapping_reliefmapping.integer)
4547                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4548                 }
4549                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4550                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4551                 // ambient model lighting
4552                 mode = SHADERMODE_LIGHTDIRECTION;
4553                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4554                         permutation |= SHADERPERMUTATION_GLOW;
4555                 if (r_refdef.fogenabled)
4556                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4557                 if (rsurface.texture->colormapping)
4558                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4559                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4560                         permutation |= SHADERPERMUTATION_REFLECTION;
4561                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4562                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4563                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4564                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4565                 {
4566                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4567                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4568                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4569                 }
4570                 else
4571                 {
4572                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4573                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4574                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4575                 }
4576                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4577                 R_Mesh_ColorPointer(NULL, 0, 0);
4578                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4579                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4580         }
4581         else
4582         {
4583                 if (r_glsl_offsetmapping.integer)
4584                 {
4585                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4586                         if (r_glsl_offsetmapping_reliefmapping.integer)
4587                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4588                 }
4589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4590                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4591                 // lightmapped wall
4592                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4593                         permutation |= SHADERPERMUTATION_GLOW;
4594                 if (r_refdef.fogenabled)
4595                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4596                 if (rsurface.texture->colormapping)
4597                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4598                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4599                         permutation |= SHADERPERMUTATION_REFLECTION;
4600                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4601                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4602                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4603                 {
4604                         // deluxemapping (light direction texture)
4605                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4606                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4607                         else
4608                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4609                         permutation |= SHADERPERMUTATION_DIFFUSE;
4610                         if (specularscale > 0)
4611                         {
4612                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4613                                 if (r_shadow_glossexact.integer)
4614                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4615                         }
4616                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4617                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4618                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4619                         else
4620                                 R_Mesh_ColorPointer(NULL, 0, 0);
4621                 }
4622                 else if (r_glsl_deluxemapping.integer >= 2)
4623                 {
4624                         // fake deluxemapping (uniform light direction in tangentspace)
4625                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4626                         permutation |= SHADERPERMUTATION_DIFFUSE;
4627                         if (specularscale > 0)
4628                         {
4629                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4630                                 if (r_shadow_glossexact.integer)
4631                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4632                         }
4633                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4634                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4635                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4636                         else
4637                                 R_Mesh_ColorPointer(NULL, 0, 0);
4638                 }
4639                 else if (rsurface.uselightmaptexture)
4640                 {
4641                         // ordinary lightmapping (q1bsp, q3bsp)
4642                         mode = SHADERMODE_LIGHTMAP;
4643                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4644                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4645                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4646                         else
4647                                 R_Mesh_ColorPointer(NULL, 0, 0);
4648                 }
4649                 else
4650                 {
4651                         // ordinary vertex coloring (q3bsp)
4652                         mode = SHADERMODE_VERTEXCOLOR;
4653                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4654                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4655                 }
4656                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4657                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4658                 {
4659                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4660                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4661                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4662                 }
4663                 else
4664                 {
4665                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4666                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4667                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4668                 }
4669                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4670                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4671         }
4672         switch(vid.renderpath)
4673         {
4674         case RENDERPATH_GL20:
4675                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4676                 if (mode == SHADERMODE_LIGHTSOURCE)
4677                 {
4678                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4679                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4680                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4681                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
4682                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
4683                         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);
4684         
4685                         // additive passes are only darkened by fog, not tinted
4686                         if (r_glsl_permutation->loc_FogColor >= 0)
4687                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4688                         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]);
4689                         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]);
4690                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4691                 }
4692                 else
4693                 {
4694                         if (mode == SHADERMODE_FLATCOLOR)
4695                         {
4696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4697                         }
4698                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4699                         {
4700                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
4701                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4702                                 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);
4703                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
4704                                 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);
4705                                 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]);
4706                                 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]);
4707                         }
4708                         else
4709                         {
4710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
4711                                 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]);
4712                                 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);
4713                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
4714                                 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);
4715                         }
4716                         // additive passes are only darkened by fog, not tinted
4717                         if (r_glsl_permutation->loc_FogColor >= 0)
4718                         {
4719                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4720                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4721                                 else
4722                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4723                         }
4724                         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);
4725                         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]);
4726                         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]);
4727                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4728                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4729                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4730                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4731                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4732                 }
4733                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4734                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4735                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4736                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4737                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4738                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4739                 {
4740                         if (rsurface.texture->pantstexture)
4741                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4742                         else
4743                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4744                 }
4745                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4746                 {
4747                         if (rsurface.texture->shirttexture)
4748                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4749                         else
4750                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4751                 }
4752                 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]);
4753                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4754                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4755                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4756                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4757                 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]);
4758                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4759
4760         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4761         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4762         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4763                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4764                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4765                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4766                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4767                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4768                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4769                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4770                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4771                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4772                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4773                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4774                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4775                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4776                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4777                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4778                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4779                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4780                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4781                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4782                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4783                 if (rsurface.rtlight)
4784                 {
4785                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4786                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4787                         if (r_shadow_usingshadowmapcube)
4788                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4789                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4790                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4791                 }
4792                 CHECKGLERROR
4793                 break;
4794         case RENDERPATH_CGGL:
4795 #ifdef SUPPORTCG
4796                 R_SetupShader_SetPermutationCG(mode, permutation);
4797                 if (mode == SHADERMODE_LIGHTSOURCE)
4798                 {
4799                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4800                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4801                 }
4802                 else
4803                 {
4804                         if (mode == SHADERMODE_LIGHTDIRECTION)
4805                         {
4806                                 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
4807                         }
4808                 }
4809                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4810                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4811                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4812                 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
4813                 CHECKGLERROR
4814
4815                 if (mode == SHADERMODE_LIGHTSOURCE)
4816                 {
4817                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4818                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4819                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
4820                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
4821                         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
4822
4823                         // additive passes are only darkened by fog, not tinted
4824                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4825                         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
4826                         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
4827                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4828                 }
4829                 else
4830                 {
4831                         if (mode == SHADERMODE_FLATCOLOR)
4832                         {
4833                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4834                         }
4835                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4836                         {
4837                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
4838                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4839                                 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
4840                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4841                                 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
4842                                 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
4843                                 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
4844                         }
4845                         else
4846                         {
4847                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
4848                                 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
4849                                 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
4850                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4851                                 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
4852                         }
4853                         // additive passes are only darkened by fog, not tinted
4854                         if (r_cg_permutation->fp_FogColor)
4855                         {
4856                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4857                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4858                                 else
4859                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4860                                 CHECKCGERROR
4861                         }
4862                         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
4863                         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
4864                         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
4865                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4866                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4867                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4868                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4869                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4870                 }
4871                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4872                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4873                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4874                 if (r_cg_permutation->fp_Color_Pants)
4875                 {
4876                         if (rsurface.texture->pantstexture)
4877                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4878                         else
4879                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4880                         CHECKCGERROR
4881                 }
4882                 if (r_cg_permutation->fp_Color_Shirt)
4883                 {
4884                         if (rsurface.texture->shirttexture)
4885                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4886                         else
4887                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4888                         CHECKCGERROR
4889                 }
4890                 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
4891                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4892                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4893                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4894                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4895                 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
4896                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4897
4898         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4899         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4900         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4901                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4902                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4903                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4904                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4905                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4906                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4907                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4908                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4909                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4910                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4911                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4912                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4913                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4914                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4915                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4916                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4917                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4918                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4919                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4920                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4921                 if (rsurface.rtlight)
4922                 {
4923                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4924                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4925                         if (r_shadow_usingshadowmapcube)
4926                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4927                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4928                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4929                 }
4930
4931                 CHECKGLERROR
4932 #endif
4933                 break;
4934         case RENDERPATH_GL13:
4935         case RENDERPATH_GL11:
4936                 break;
4937         }
4938 }
4939
4940 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4941 {
4942         // select a permutation of the lighting shader appropriate to this
4943         // combination of texture, entity, light source, and fogging, only use the
4944         // minimum features necessary to avoid wasting rendering time in the
4945         // fragment shader on features that are not being used
4946         unsigned int permutation = 0;
4947         unsigned int mode = 0;
4948         const float *lightcolorbase = rtlight->currentcolor;
4949         float ambientscale = rtlight->ambientscale;
4950         float diffusescale = rtlight->diffusescale;
4951         float specularscale = rtlight->specularscale;
4952         // this is the location of the light in view space
4953         vec3_t viewlightorigin;
4954         // this transforms from view space (camera) to light space (cubemap)
4955         matrix4x4_t viewtolight;
4956         matrix4x4_t lighttoview;
4957         float viewtolight16f[16];
4958         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4959         // light source
4960         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4961         if (rtlight->currentcubemap != r_texture_whitecube)
4962                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4963         if (diffusescale > 0)
4964                 permutation |= SHADERPERMUTATION_DIFFUSE;
4965         if (specularscale > 0)
4966         {
4967                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4968                 if (r_shadow_glossexact.integer)
4969                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4970         }
4971         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4972         {
4973                 if (r_shadow_usingshadowmaprect)
4974                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4975                 if (r_shadow_usingshadowmap2d)
4976                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4977                 if (r_shadow_usingshadowmapcube)
4978                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4979                 else if(r_shadow_shadowmapvsdct)
4980                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4981
4982                 if (r_shadow_shadowmapsampler)
4983                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4984                 if (r_shadow_shadowmappcf > 1)
4985                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4986                 else if (r_shadow_shadowmappcf)
4987                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4988         }
4989         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4990         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4991         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4992         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4993         switch(vid.renderpath)
4994         {
4995         case RENDERPATH_GL20:
4996                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4997                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4998                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4999                 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);
5000                 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);
5001                 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);
5002                 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]);
5003                 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]);
5004                 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));
5005                 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]);
5006                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5007
5008                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5009                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5010                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5011                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5012                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5013                 if (r_shadow_usingshadowmapcube)
5014                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5015                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5016                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5017                 break;
5018         case RENDERPATH_CGGL:
5019 #ifdef SUPPORTCG
5020                 R_SetupShader_SetPermutationCG(mode, permutation);
5021                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5022                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5023                 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
5024                 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
5025                 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
5026                 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
5027                 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
5028                 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
5029                 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
5030                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5031
5032                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5033                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5034                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5035                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5036                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5037                 if (r_shadow_usingshadowmapcube)
5038                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5039                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5040                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5041 #endif
5042                 break;
5043         case RENDERPATH_GL13:
5044         case RENDERPATH_GL11:
5045                 break;
5046         }
5047 }
5048
5049 #define SKINFRAME_HASH 1024
5050
5051 typedef struct
5052 {
5053         int loadsequence; // incremented each level change
5054         memexpandablearray_t array;
5055         skinframe_t *hash[SKINFRAME_HASH];
5056 }
5057 r_skinframe_t;
5058 r_skinframe_t r_skinframe;
5059
5060 void R_SkinFrame_PrepareForPurge(void)
5061 {
5062         r_skinframe.loadsequence++;
5063         // wrap it without hitting zero
5064         if (r_skinframe.loadsequence >= 200)
5065                 r_skinframe.loadsequence = 1;
5066 }
5067
5068 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5069 {
5070         if (!skinframe)
5071                 return;
5072         // mark the skinframe as used for the purging code
5073         skinframe->loadsequence = r_skinframe.loadsequence;
5074 }
5075
5076 void R_SkinFrame_Purge(void)
5077 {
5078         int i;
5079         skinframe_t *s;
5080         for (i = 0;i < SKINFRAME_HASH;i++)
5081         {
5082                 for (s = r_skinframe.hash[i];s;s = s->next)
5083                 {
5084                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5085                         {
5086                                 if (s->merged == s->base)
5087                                         s->merged = NULL;
5088                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5089                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5090                                 R_PurgeTexture(s->merged);s->merged = NULL;
5091                                 R_PurgeTexture(s->base  );s->base   = NULL;
5092                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5093                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5094                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5095                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5096                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5097                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5098                                 s->loadsequence = 0;
5099                         }
5100                 }
5101         }
5102 }
5103
5104 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5105         skinframe_t *item;
5106         char basename[MAX_QPATH];
5107
5108         Image_StripImageExtension(name, basename, sizeof(basename));
5109
5110         if( last == NULL ) {
5111                 int hashindex;
5112                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5113                 item = r_skinframe.hash[hashindex];
5114         } else {
5115                 item = last->next;
5116         }
5117
5118         // linearly search through the hash bucket
5119         for( ; item ; item = item->next ) {
5120                 if( !strcmp( item->basename, basename ) ) {
5121                         return item;
5122                 }
5123         }
5124         return NULL;
5125 }
5126
5127 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5128 {
5129         skinframe_t *item;
5130         int hashindex;
5131         char basename[MAX_QPATH];
5132
5133         Image_StripImageExtension(name, basename, sizeof(basename));
5134
5135         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5136         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5137                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5138                         break;
5139
5140         if (!item) {
5141                 rtexture_t *dyntexture;
5142                 // check whether its a dynamic texture
5143                 dyntexture = CL_GetDynTexture( basename );
5144                 if (!add && !dyntexture)
5145                         return NULL;
5146                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5147                 memset(item, 0, sizeof(*item));
5148                 strlcpy(item->basename, basename, sizeof(item->basename));
5149                 item->base = dyntexture; // either NULL or dyntexture handle
5150                 item->textureflags = textureflags;
5151                 item->comparewidth = comparewidth;
5152                 item->compareheight = compareheight;
5153                 item->comparecrc = comparecrc;
5154                 item->next = r_skinframe.hash[hashindex];
5155                 r_skinframe.hash[hashindex] = item;
5156         }
5157         else if( item->base == NULL )
5158         {
5159                 rtexture_t *dyntexture;
5160                 // check whether its a dynamic texture
5161                 // 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]
5162                 dyntexture = CL_GetDynTexture( basename );
5163                 item->base = dyntexture; // either NULL or dyntexture handle
5164         }
5165
5166         R_SkinFrame_MarkUsed(item);
5167         return item;
5168 }
5169
5170 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5171         { \
5172                 unsigned long long avgcolor[5], wsum; \
5173                 int pix, comp, w; \
5174                 avgcolor[0] = 0; \
5175                 avgcolor[1] = 0; \
5176                 avgcolor[2] = 0; \
5177                 avgcolor[3] = 0; \
5178                 avgcolor[4] = 0; \
5179                 wsum = 0; \
5180                 for(pix = 0; pix < cnt; ++pix) \
5181                 { \
5182                         w = 0; \
5183                         for(comp = 0; comp < 3; ++comp) \
5184                                 w += getpixel; \
5185                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5186                         { \
5187                                 ++wsum; \
5188                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5189                                 w = getpixel; \
5190                                 for(comp = 0; comp < 3; ++comp) \
5191                                         avgcolor[comp] += getpixel * w; \
5192                                 avgcolor[3] += w; \
5193                         } \
5194                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5195                         avgcolor[4] += getpixel; \
5196                 } \
5197                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5198                         avgcolor[3] = 1; \
5199                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5200                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5201                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5202                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5203         }
5204
5205 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5206 {
5207         int j;
5208         unsigned char *pixels;
5209         unsigned char *bumppixels;
5210         unsigned char *basepixels = NULL;
5211         int basepixels_width = 0;
5212         int basepixels_height = 0;
5213         skinframe_t *skinframe;
5214         rtexture_t *ddsbase = NULL;
5215         qboolean ddshasalpha = false;
5216         float ddsavgcolor[4];
5217         char basename[MAX_QPATH];
5218
5219         if (cls.state == ca_dedicated)
5220                 return NULL;
5221
5222         // return an existing skinframe if already loaded
5223         // if loading of the first image fails, don't make a new skinframe as it
5224         // would cause all future lookups of this to be missing
5225         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5226         if (skinframe && skinframe->base)
5227                 return skinframe;
5228
5229         Image_StripImageExtension(name, basename, sizeof(basename));
5230
5231         // check for DDS texture file first
5232         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5233         {
5234                 basepixels = loadimagepixelsbgra(name, complain, true);
5235                 if (basepixels == NULL)
5236                         return NULL;
5237         }
5238
5239         if (developer_loading.integer)
5240                 Con_Printf("loading skin \"%s\"\n", name);
5241
5242         // we've got some pixels to store, so really allocate this new texture now
5243         if (!skinframe)
5244                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5245         skinframe->stain = NULL;
5246         skinframe->merged = NULL;
5247         skinframe->base = NULL;
5248         skinframe->pants = NULL;
5249         skinframe->shirt = NULL;
5250         skinframe->nmap = NULL;
5251         skinframe->gloss = NULL;
5252         skinframe->glow = NULL;
5253         skinframe->fog = NULL;
5254         skinframe->hasalpha = false;
5255
5256         if (ddsbase)
5257         {
5258                 skinframe->base = ddsbase;
5259                 skinframe->hasalpha = ddshasalpha;
5260                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5261                 if (r_loadfog && skinframe->hasalpha)
5262                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5263                 //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]);
5264         }
5265         else
5266         {
5267                 basepixels_width = image_width;
5268                 basepixels_height = image_height;
5269                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5270                 if (textureflags & TEXF_ALPHA)
5271                 {
5272                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5273                         {
5274                                 if (basepixels[j] < 255)
5275                                 {
5276                                         skinframe->hasalpha = true;
5277                                         break;
5278                                 }
5279                         }
5280                         if (r_loadfog && skinframe->hasalpha)
5281                         {
5282                                 // has transparent pixels
5283                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5284                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5285                                 {
5286                                         pixels[j+0] = 255;
5287                                         pixels[j+1] = 255;
5288                                         pixels[j+2] = 255;
5289                                         pixels[j+3] = basepixels[j+3];
5290                                 }
5291                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5292                                 Mem_Free(pixels);
5293                         }
5294                 }
5295                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5296                 //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]);
5297                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5298                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5299                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5300                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5301         }
5302
5303         if (r_loaddds)
5304         {
5305                 if (r_loadnormalmap)
5306                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5307                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5308                 if (r_loadgloss)
5309                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5310                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5311                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5312         }
5313
5314         // _norm is the name used by tenebrae and has been adopted as standard
5315         if (r_loadnormalmap && skinframe->nmap == NULL)
5316         {
5317                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5318                 {
5319                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5320                         Mem_Free(pixels);
5321                         pixels = NULL;
5322                 }
5323                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5324                 {
5325                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5326                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5327                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5328                         Mem_Free(pixels);
5329                         Mem_Free(bumppixels);
5330                 }
5331                 else if (r_shadow_bumpscale_basetexture.value > 0)
5332                 {
5333                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5334                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5335                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5336                         Mem_Free(pixels);
5337                 }
5338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5339                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5340         }
5341
5342         // _luma is supported only for tenebrae compatibility
5343         // _glow is the preferred name
5344         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5345         {
5346                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5347                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5348                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5349                 Mem_Free(pixels);pixels = NULL;
5350         }
5351
5352         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5353         {
5354                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5356                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5357                 Mem_Free(pixels);
5358                 pixels = NULL;
5359         }
5360
5361         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5362         {
5363                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5364                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5365                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5366                 Mem_Free(pixels);
5367                 pixels = NULL;
5368         }
5369
5370         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5371         {
5372                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5373                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5374                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5375                 Mem_Free(pixels);
5376                 pixels = NULL;
5377         }
5378
5379         if (basepixels)
5380                 Mem_Free(basepixels);
5381
5382         return skinframe;
5383 }
5384
5385 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5386 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5387 {
5388         int i;
5389         unsigned char *temp1, *temp2;
5390         skinframe_t *skinframe;
5391
5392         if (cls.state == ca_dedicated)
5393                 return NULL;
5394
5395         // if already loaded just return it, otherwise make a new skinframe
5396         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5397         if (skinframe && skinframe->base)
5398                 return skinframe;
5399
5400         skinframe->stain = NULL;
5401         skinframe->merged = NULL;
5402         skinframe->base = NULL;
5403         skinframe->pants = NULL;
5404         skinframe->shirt = NULL;
5405         skinframe->nmap = NULL;
5406         skinframe->gloss = NULL;
5407         skinframe->glow = NULL;
5408         skinframe->fog = NULL;
5409         skinframe->hasalpha = false;
5410
5411         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5412         if (!skindata)
5413                 return NULL;
5414
5415         if (developer_loading.integer)
5416                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5417
5418         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5419         {
5420                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5421                 temp2 = temp1 + width * height * 4;
5422                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5423                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5424                 Mem_Free(temp1);
5425         }
5426         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5427         if (textureflags & TEXF_ALPHA)
5428         {
5429                 for (i = 3;i < width * height * 4;i += 4)
5430                 {
5431                         if (skindata[i] < 255)
5432                         {
5433                                 skinframe->hasalpha = true;
5434                                 break;
5435                         }
5436                 }
5437                 if (r_loadfog && skinframe->hasalpha)
5438                 {
5439                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5440                         memcpy(fogpixels, skindata, width * height * 4);
5441                         for (i = 0;i < width * height * 4;i += 4)
5442                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5443                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5444                         Mem_Free(fogpixels);
5445                 }
5446         }
5447
5448         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5449         //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]);
5450
5451         return skinframe;
5452 }
5453
5454 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5455 {
5456         int i;
5457         int featuresmask;
5458         skinframe_t *skinframe;
5459
5460         if (cls.state == ca_dedicated)
5461                 return NULL;
5462
5463         // if already loaded just return it, otherwise make a new skinframe
5464         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5465         if (skinframe && skinframe->base)
5466                 return skinframe;
5467
5468         skinframe->stain = NULL;
5469         skinframe->merged = NULL;
5470         skinframe->base = NULL;
5471         skinframe->pants = NULL;
5472         skinframe->shirt = NULL;
5473         skinframe->nmap = NULL;
5474         skinframe->gloss = NULL;
5475         skinframe->glow = NULL;
5476         skinframe->fog = NULL;
5477         skinframe->hasalpha = false;
5478
5479         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5480         if (!skindata)
5481                 return NULL;
5482
5483         if (developer_loading.integer)
5484                 Con_Printf("loading quake skin \"%s\"\n", name);
5485
5486         // 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)
5487         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5488         memcpy(skinframe->qpixels, skindata, width*height);
5489         skinframe->qwidth = width;
5490         skinframe->qheight = height;
5491
5492         featuresmask = 0;
5493         for (i = 0;i < width * height;i++)
5494                 featuresmask |= palette_featureflags[skindata[i]];
5495
5496         skinframe->hasalpha = false;
5497         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5498         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5499         skinframe->qgeneratemerged = true;
5500         skinframe->qgeneratebase = skinframe->qhascolormapping;
5501         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5502
5503         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5504         //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]);
5505
5506         return skinframe;
5507 }
5508
5509 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5510 {
5511         int width;
5512         int height;
5513         unsigned char *skindata;
5514
5515         if (!skinframe->qpixels)
5516                 return;
5517
5518         if (!skinframe->qhascolormapping)
5519                 colormapped = false;
5520
5521         if (colormapped)
5522         {
5523                 if (!skinframe->qgeneratebase)
5524                         return;
5525         }
5526         else
5527         {
5528                 if (!skinframe->qgeneratemerged)
5529                         return;
5530         }
5531
5532         width = skinframe->qwidth;
5533         height = skinframe->qheight;
5534         skindata = skinframe->qpixels;
5535
5536         if (skinframe->qgeneratenmap)
5537         {
5538                 unsigned char *temp1, *temp2;
5539                 skinframe->qgeneratenmap = false;
5540                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5541                 temp2 = temp1 + width * height * 4;
5542                 // use either a custom palette or the quake palette
5543                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5544                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5545                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5546                 Mem_Free(temp1);
5547         }
5548
5549         if (skinframe->qgenerateglow)
5550         {
5551                 skinframe->qgenerateglow = false;
5552                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5553         }
5554
5555         if (colormapped)
5556         {
5557                 skinframe->qgeneratebase = false;
5558                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5559                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5560                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5561         }
5562         else
5563         {
5564                 skinframe->qgeneratemerged = false;
5565                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5566         }
5567
5568         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5569         {
5570                 Mem_Free(skinframe->qpixels);
5571                 skinframe->qpixels = NULL;
5572         }
5573 }
5574
5575 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)
5576 {
5577         int i;
5578         skinframe_t *skinframe;
5579
5580         if (cls.state == ca_dedicated)
5581                 return NULL;
5582
5583         // if already loaded just return it, otherwise make a new skinframe
5584         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5585         if (skinframe && skinframe->base)
5586                 return skinframe;
5587
5588         skinframe->stain = NULL;
5589         skinframe->merged = NULL;
5590         skinframe->base = NULL;
5591         skinframe->pants = NULL;
5592         skinframe->shirt = NULL;
5593         skinframe->nmap = NULL;
5594         skinframe->gloss = NULL;
5595         skinframe->glow = NULL;
5596         skinframe->fog = NULL;
5597         skinframe->hasalpha = false;
5598
5599         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5600         if (!skindata)
5601                 return NULL;
5602
5603         if (developer_loading.integer)
5604                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5605
5606         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5607         if (textureflags & TEXF_ALPHA)
5608         {
5609                 for (i = 0;i < width * height;i++)
5610                 {
5611                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5612                         {
5613                                 skinframe->hasalpha = true;
5614                                 break;
5615                         }
5616                 }
5617                 if (r_loadfog && skinframe->hasalpha)
5618                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5619         }
5620
5621         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5622         //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]);
5623
5624         return skinframe;
5625 }
5626
5627 skinframe_t *R_SkinFrame_LoadMissing(void)
5628 {
5629         skinframe_t *skinframe;
5630
5631         if (cls.state == ca_dedicated)
5632                 return NULL;
5633
5634         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5635         skinframe->stain = NULL;
5636         skinframe->merged = NULL;
5637         skinframe->base = NULL;
5638         skinframe->pants = NULL;
5639         skinframe->shirt = NULL;
5640         skinframe->nmap = NULL;
5641         skinframe->gloss = NULL;
5642         skinframe->glow = NULL;
5643         skinframe->fog = NULL;
5644         skinframe->hasalpha = false;
5645
5646         skinframe->avgcolor[0] = rand() / RAND_MAX;
5647         skinframe->avgcolor[1] = rand() / RAND_MAX;
5648         skinframe->avgcolor[2] = rand() / RAND_MAX;
5649         skinframe->avgcolor[3] = 1;
5650
5651         return skinframe;
5652 }
5653
5654 void R_Main_FreeViewCache(void)
5655 {
5656         if (r_refdef.viewcache.entityvisible)
5657                 Mem_Free(r_refdef.viewcache.entityvisible);
5658         if (r_refdef.viewcache.world_pvsbits)
5659                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5660         if (r_refdef.viewcache.world_leafvisible)
5661                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5662         if (r_refdef.viewcache.world_surfacevisible)
5663                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5664         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5665 }
5666
5667 void R_Main_ResizeViewCache(void)
5668 {
5669         int numentities = r_refdef.scene.numentities;
5670         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5671         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5672         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5673         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5674         if (r_refdef.viewcache.maxentities < numentities)
5675         {
5676                 r_refdef.viewcache.maxentities = numentities;
5677                 if (r_refdef.viewcache.entityvisible)
5678                         Mem_Free(r_refdef.viewcache.entityvisible);
5679                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5680         }
5681         if (r_refdef.viewcache.world_numclusters != numclusters)
5682         {
5683                 r_refdef.viewcache.world_numclusters = numclusters;
5684                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5685                 if (r_refdef.viewcache.world_pvsbits)
5686                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5687                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5688         }
5689         if (r_refdef.viewcache.world_numleafs != numleafs)
5690         {
5691                 r_refdef.viewcache.world_numleafs = numleafs;
5692                 if (r_refdef.viewcache.world_leafvisible)
5693                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5694                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5695         }
5696         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5697         {
5698                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5699                 if (r_refdef.viewcache.world_surfacevisible)
5700                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5701                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5702         }
5703 }
5704
5705 extern rtexture_t *loadingscreentexture;
5706 void gl_main_start(void)
5707 {
5708         loadingscreentexture = NULL;
5709         r_texture_blanknormalmap = NULL;
5710         r_texture_white = NULL;
5711         r_texture_grey128 = NULL;
5712         r_texture_black = NULL;
5713         r_texture_whitecube = NULL;
5714         r_texture_normalizationcube = NULL;
5715         r_texture_fogattenuation = NULL;
5716         r_texture_gammaramps = NULL;
5717
5718         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5719         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5720
5721         switch(vid.renderpath)
5722         {
5723         case RENDERPATH_GL20:
5724         case RENDERPATH_CGGL:
5725                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5726                 Cvar_SetValueQuick(&gl_combine, 1);
5727                 Cvar_SetValueQuick(&r_glsl, 1);
5728                 r_loadnormalmap = true;
5729                 r_loadgloss = true;
5730                 r_loadfog = false;
5731                 break;
5732         case RENDERPATH_GL13:
5733                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5734                 Cvar_SetValueQuick(&gl_combine, 1);
5735                 Cvar_SetValueQuick(&r_glsl, 0);
5736                 r_loadnormalmap = false;
5737                 r_loadgloss = false;
5738                 r_loadfog = true;
5739                 break;
5740         case RENDERPATH_GL11:
5741                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5742                 Cvar_SetValueQuick(&gl_combine, 0);
5743                 Cvar_SetValueQuick(&r_glsl, 0);
5744                 r_loadnormalmap = false;
5745                 r_loadgloss = false;
5746                 r_loadfog = true;
5747                 break;
5748         }
5749
5750         R_AnimCache_Free();
5751         R_FrameData_Reset();
5752
5753         r_numqueries = 0;
5754         r_maxqueries = 0;
5755         memset(r_queries, 0, sizeof(r_queries));
5756
5757         r_qwskincache = NULL;
5758         r_qwskincache_size = 0;
5759
5760         // set up r_skinframe loading system for textures
5761         memset(&r_skinframe, 0, sizeof(r_skinframe));
5762         r_skinframe.loadsequence = 1;
5763         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5764
5765         r_main_texturepool = R_AllocTexturePool();
5766         R_BuildBlankTextures();
5767         R_BuildNoTexture();
5768         if (vid.support.arb_texture_cube_map)
5769         {
5770                 R_BuildWhiteCube();
5771                 R_BuildNormalizationCube();
5772         }
5773         r_texture_fogattenuation = NULL;
5774         r_texture_gammaramps = NULL;
5775         //r_texture_fogintensity = NULL;
5776         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5777         memset(&r_waterstate, 0, sizeof(r_waterstate));
5778         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5779         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5780 #ifdef SUPPORTCG
5781         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5782         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5783 #endif
5784         memset(&r_svbsp, 0, sizeof (r_svbsp));
5785
5786         r_refdef.fogmasktable_density = 0;
5787 }
5788
5789 void gl_main_shutdown(void)
5790 {
5791         R_AnimCache_Free();
5792         R_FrameData_Reset();
5793
5794         R_Main_FreeViewCache();
5795
5796         if (r_maxqueries)
5797                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5798
5799         r_numqueries = 0;
5800         r_maxqueries = 0;
5801         memset(r_queries, 0, sizeof(r_queries));
5802
5803         r_qwskincache = NULL;
5804         r_qwskincache_size = 0;
5805
5806         // clear out the r_skinframe state
5807         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5808         memset(&r_skinframe, 0, sizeof(r_skinframe));
5809
5810         if (r_svbsp.nodes)
5811                 Mem_Free(r_svbsp.nodes);
5812         memset(&r_svbsp, 0, sizeof (r_svbsp));
5813         R_FreeTexturePool(&r_main_texturepool);
5814         loadingscreentexture = NULL;
5815         r_texture_blanknormalmap = NULL;
5816         r_texture_white = NULL;
5817         r_texture_grey128 = NULL;
5818         r_texture_black = NULL;
5819         r_texture_whitecube = NULL;
5820         r_texture_normalizationcube = NULL;
5821         r_texture_fogattenuation = NULL;
5822         r_texture_gammaramps = NULL;
5823         //r_texture_fogintensity = NULL;
5824         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5825         memset(&r_waterstate, 0, sizeof(r_waterstate));
5826         R_GLSL_Restart_f();
5827 }
5828
5829 extern void CL_ParseEntityLump(char *entitystring);
5830 void gl_main_newmap(void)
5831 {
5832         // FIXME: move this code to client
5833         int l;
5834         char *entities, entname[MAX_QPATH];
5835         if (r_qwskincache)
5836                 Mem_Free(r_qwskincache);
5837         r_qwskincache = NULL;
5838         r_qwskincache_size = 0;
5839         if (cl.worldmodel)
5840         {
5841                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5842                 l = (int)strlen(entname) - 4;
5843                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5844                 {
5845                         memcpy(entname + l, ".ent", 5);
5846                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5847                         {
5848                                 CL_ParseEntityLump(entities);
5849                                 Mem_Free(entities);
5850                                 return;
5851                         }
5852                 }
5853                 if (cl.worldmodel->brush.entities)
5854                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5855         }
5856         R_Main_FreeViewCache();
5857
5858         R_FrameData_Reset();
5859 }
5860
5861 void GL_Main_Init(void)
5862 {
5863         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5864
5865         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5866         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5867         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5868         if (gamemode == GAME_NEHAHRA)
5869         {
5870                 Cvar_RegisterVariable (&gl_fogenable);
5871                 Cvar_RegisterVariable (&gl_fogdensity);
5872                 Cvar_RegisterVariable (&gl_fogred);
5873                 Cvar_RegisterVariable (&gl_foggreen);
5874                 Cvar_RegisterVariable (&gl_fogblue);
5875                 Cvar_RegisterVariable (&gl_fogstart);
5876                 Cvar_RegisterVariable (&gl_fogend);
5877                 Cvar_RegisterVariable (&gl_skyclip);
5878         }
5879         Cvar_RegisterVariable(&r_motionblur);
5880         Cvar_RegisterVariable(&r_motionblur_maxblur);
5881         Cvar_RegisterVariable(&r_motionblur_bmin);
5882         Cvar_RegisterVariable(&r_motionblur_vmin);
5883         Cvar_RegisterVariable(&r_motionblur_vmax);
5884         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5885         Cvar_RegisterVariable(&r_motionblur_randomize);
5886         Cvar_RegisterVariable(&r_damageblur);
5887         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5888         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5889         Cvar_RegisterVariable(&r_equalize_entities_by);
5890         Cvar_RegisterVariable(&r_equalize_entities_to);
5891         Cvar_RegisterVariable(&r_depthfirst);
5892         Cvar_RegisterVariable(&r_useinfinitefarclip);
5893         Cvar_RegisterVariable(&r_farclip_base);
5894         Cvar_RegisterVariable(&r_farclip_world);
5895         Cvar_RegisterVariable(&r_nearclip);
5896         Cvar_RegisterVariable(&r_showbboxes);
5897         Cvar_RegisterVariable(&r_showsurfaces);
5898         Cvar_RegisterVariable(&r_showtris);
5899         Cvar_RegisterVariable(&r_shownormals);
5900         Cvar_RegisterVariable(&r_showlighting);
5901         Cvar_RegisterVariable(&r_showshadowvolumes);
5902         Cvar_RegisterVariable(&r_showcollisionbrushes);
5903         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5904         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5905         Cvar_RegisterVariable(&r_showdisabledepthtest);
5906         Cvar_RegisterVariable(&r_drawportals);
5907         Cvar_RegisterVariable(&r_drawentities);
5908         Cvar_RegisterVariable(&r_cullentities_trace);
5909         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5910         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5911         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5912         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5913         Cvar_RegisterVariable(&r_drawviewmodel);
5914         Cvar_RegisterVariable(&r_speeds);
5915         Cvar_RegisterVariable(&r_fullbrights);
5916         Cvar_RegisterVariable(&r_wateralpha);
5917         Cvar_RegisterVariable(&r_dynamic);
5918         Cvar_RegisterVariable(&r_fullbright);
5919         Cvar_RegisterVariable(&r_shadows);
5920         Cvar_RegisterVariable(&r_shadows_darken);
5921         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5922         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5923         Cvar_RegisterVariable(&r_shadows_throwdistance);
5924         Cvar_RegisterVariable(&r_shadows_throwdirection);
5925         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5926         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5927         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5928         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5929         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5930         Cvar_RegisterVariable(&r_fog_exp2);
5931         Cvar_RegisterVariable(&r_drawfog);
5932         Cvar_RegisterVariable(&r_transparentdepthmasking);
5933         Cvar_RegisterVariable(&r_texture_dds_load);
5934         Cvar_RegisterVariable(&r_texture_dds_save);
5935         Cvar_RegisterVariable(&r_textureunits);
5936         Cvar_RegisterVariable(&gl_combine);
5937         Cvar_RegisterVariable(&r_glsl);
5938         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5939         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5940         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5941         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5942         Cvar_RegisterVariable(&r_glsl_postprocess);
5943         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5944         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5945         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5946         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5947         Cvar_RegisterVariable(&r_water);
5948         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5949         Cvar_RegisterVariable(&r_water_clippingplanebias);
5950         Cvar_RegisterVariable(&r_water_refractdistort);
5951         Cvar_RegisterVariable(&r_water_reflectdistort);
5952         Cvar_RegisterVariable(&r_lerpsprites);
5953         Cvar_RegisterVariable(&r_lerpmodels);
5954         Cvar_RegisterVariable(&r_lerplightstyles);
5955         Cvar_RegisterVariable(&r_waterscroll);
5956         Cvar_RegisterVariable(&r_bloom);
5957         Cvar_RegisterVariable(&r_bloom_colorscale);
5958         Cvar_RegisterVariable(&r_bloom_brighten);
5959         Cvar_RegisterVariable(&r_bloom_blur);
5960         Cvar_RegisterVariable(&r_bloom_resolution);
5961         Cvar_RegisterVariable(&r_bloom_colorexponent);
5962         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5963         Cvar_RegisterVariable(&r_hdr);
5964         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5965         Cvar_RegisterVariable(&r_hdr_glowintensity);
5966         Cvar_RegisterVariable(&r_hdr_range);
5967         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5968         Cvar_RegisterVariable(&developer_texturelogging);
5969         Cvar_RegisterVariable(&gl_lightmaps);
5970         Cvar_RegisterVariable(&r_test);
5971         Cvar_RegisterVariable(&r_batchmode);
5972         Cvar_RegisterVariable(&r_glsl_saturation);
5973         Cvar_RegisterVariable(&r_framedatasize);
5974         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5975                 Cvar_SetValue("r_fullbrights", 0);
5976         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5977
5978         Cvar_RegisterVariable(&r_track_sprites);
5979         Cvar_RegisterVariable(&r_track_sprites_flags);
5980         Cvar_RegisterVariable(&r_track_sprites_scalew);
5981         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5982         Cvar_RegisterVariable(&r_overheadsprites_perspective);
5983         Cvar_RegisterVariable(&r_overheadsprites_pushback);
5984 }
5985
5986 extern void R_Textures_Init(void);
5987 extern void GL_Draw_Init(void);
5988 extern void GL_Main_Init(void);
5989 extern void R_Shadow_Init(void);
5990 extern void R_Sky_Init(void);
5991 extern void GL_Surf_Init(void);
5992 extern void R_Particles_Init(void);
5993 extern void R_Explosion_Init(void);
5994 extern void gl_backend_init(void);
5995 extern void Sbar_Init(void);
5996 extern void R_LightningBeams_Init(void);
5997 extern void Mod_RenderInit(void);
5998 extern void Font_Init(void);
5999
6000 void Render_Init(void)
6001 {
6002         gl_backend_init();
6003         R_Textures_Init();
6004         GL_Main_Init();
6005         Font_Init();
6006         GL_Draw_Init();
6007         R_Shadow_Init();
6008         R_Sky_Init();
6009         GL_Surf_Init();
6010         Sbar_Init();
6011         R_Particles_Init();
6012         R_Explosion_Init();
6013         R_LightningBeams_Init();
6014         Mod_RenderInit();
6015 }
6016
6017 /*
6018 ===============
6019 GL_Init
6020 ===============
6021 */
6022 extern char *ENGINE_EXTENSIONS;
6023 void GL_Init (void)
6024 {
6025         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6026         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6027         gl_version = (const char *)qglGetString(GL_VERSION);
6028         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6029
6030         if (!gl_extensions)
6031                 gl_extensions = "";
6032         if (!gl_platformextensions)
6033                 gl_platformextensions = "";
6034
6035         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6036         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6037         Con_Printf("GL_VERSION: %s\n", gl_version);
6038         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6039         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6040
6041         VID_CheckExtensions();
6042
6043         // LordHavoc: report supported extensions
6044         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6045
6046         // clear to black (loading plaque will be seen over this)
6047         CHECKGLERROR
6048         qglClearColor(0,0,0,1);CHECKGLERROR
6049         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6050 }
6051
6052 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6053 {
6054         int i;
6055         mplane_t *p;
6056         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6057         {
6058                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6059                 if (i == 4)
6060                         continue;
6061                 p = r_refdef.view.frustum + i;
6062                 switch(p->signbits)
6063                 {
6064                 default:
6065                 case 0:
6066                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6067                                 return true;
6068                         break;
6069                 case 1:
6070                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6071                                 return true;
6072                         break;
6073                 case 2:
6074                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6075                                 return true;
6076                         break;
6077                 case 3:
6078                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6079                                 return true;
6080                         break;
6081                 case 4:
6082                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6083                                 return true;
6084                         break;
6085                 case 5:
6086                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6087                                 return true;
6088                         break;
6089                 case 6:
6090                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6091                                 return true;
6092                         break;
6093                 case 7:
6094                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6095                                 return true;
6096                         break;
6097                 }
6098         }
6099         return false;
6100 }
6101
6102 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6103 {
6104         int i;
6105         const mplane_t *p;
6106         for (i = 0;i < numplanes;i++)
6107         {
6108                 p = planes + i;
6109                 switch(p->signbits)
6110                 {
6111                 default:
6112                 case 0:
6113                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6114                                 return true;
6115                         break;
6116                 case 1:
6117                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6118                                 return true;
6119                         break;
6120                 case 2:
6121                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6122                                 return true;
6123                         break;
6124                 case 3:
6125                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6126                                 return true;
6127                         break;
6128                 case 4:
6129                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6130                                 return true;
6131                         break;
6132                 case 5:
6133                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6134                                 return true;
6135                         break;
6136                 case 6:
6137                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6138                                 return true;
6139                         break;
6140                 case 7:
6141                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6142                                 return true;
6143                         break;
6144                 }
6145         }
6146         return false;
6147 }
6148
6149 //==================================================================================
6150
6151 // LordHavoc: this stores temporary data used within the same frame
6152
6153 qboolean r_framedata_failed;
6154 static size_t r_framedata_size;
6155 static size_t r_framedata_current;
6156 static void *r_framedata_base;
6157
6158 void R_FrameData_Reset(void)
6159 {
6160         if (r_framedata_base)
6161                 Mem_Free(r_framedata_base);
6162         r_framedata_base = NULL;
6163         r_framedata_size = 0;
6164         r_framedata_current = 0;
6165         r_framedata_failed = false;
6166 }
6167
6168 void R_FrameData_NewFrame(void)
6169 {
6170         size_t wantedsize;
6171         if (r_framedata_failed)
6172                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6173         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6174         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6175         if (r_framedata_size != wantedsize)
6176         {
6177                 r_framedata_size = wantedsize;
6178                 if (r_framedata_base)
6179                         Mem_Free(r_framedata_base);
6180                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6181         }
6182         r_framedata_current = 0;
6183         r_framedata_failed = false;
6184 }
6185
6186 void *R_FrameData_Alloc(size_t size)
6187 {
6188         void *data;
6189
6190         // align to 16 byte boundary
6191         size = (size + 15) & ~15;
6192         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6193         r_framedata_current += size;
6194
6195         // check overflow
6196         if (r_framedata_current > r_framedata_size)
6197                 r_framedata_failed = true;
6198
6199         // return NULL on everything after a failure
6200         if (r_framedata_failed)
6201                 return NULL;
6202
6203         return data;
6204 }
6205
6206 void *R_FrameData_Store(size_t size, void *data)
6207 {
6208         void *d = R_FrameData_Alloc(size);
6209         if (d)
6210                 memcpy(d, data, size);
6211         return d;
6212 }
6213
6214 //==================================================================================
6215
6216 // LordHavoc: animcache originally written by Echon, rewritten since then
6217
6218 /**
6219  * Animation cache prevents re-generating mesh data for an animated model
6220  * multiple times in one frame for lighting, shadowing, reflections, etc.
6221  */
6222
6223 void R_AnimCache_Free(void)
6224 {
6225 }
6226
6227 void R_AnimCache_ClearCache(void)
6228 {
6229         int i;
6230         entity_render_t *ent;
6231
6232         for (i = 0;i < r_refdef.scene.numentities;i++)
6233         {
6234                 ent = r_refdef.scene.entities[i];
6235                 ent->animcache_vertex3f = NULL;
6236                 ent->animcache_normal3f = NULL;
6237                 ent->animcache_svector3f = NULL;
6238                 ent->animcache_tvector3f = NULL;
6239         }
6240 }
6241
6242 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6243 {
6244         dp_model_t *model = ent->model;
6245         int numvertices;
6246         // see if it's already cached this frame
6247         if (ent->animcache_vertex3f)
6248         {
6249                 // add normals/tangents if needed
6250                 if (wantnormals || wanttangents)
6251                 {
6252                         if (ent->animcache_normal3f)
6253                                 wantnormals = false;
6254                         if (ent->animcache_svector3f)
6255                                 wanttangents = false;
6256                         if (wantnormals || wanttangents)
6257                         {
6258                                 numvertices = model->surfmesh.num_vertices;
6259                                 if (wantnormals)
6260                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6261                                 if (wanttangents)
6262                                 {
6263                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6264                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6265                                 }
6266                                 if (!r_framedata_failed)
6267                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6268                         }
6269                 }
6270         }
6271         else
6272         {
6273                 // see if this ent is worth caching
6274                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6275                         return false;
6276                 // get some memory for this entity and generate mesh data
6277                 numvertices = model->surfmesh.num_vertices;
6278                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6279                 if (wantnormals)
6280                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6281                 if (wanttangents)
6282                 {
6283                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6284                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6285                 }
6286                 if (!r_framedata_failed)
6287                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6288         }
6289         return !r_framedata_failed;
6290 }
6291
6292 void R_AnimCache_CacheVisibleEntities(void)
6293 {
6294         int i;
6295         qboolean wantnormals = !r_showsurfaces.integer;
6296         qboolean wanttangents = !r_showsurfaces.integer;
6297
6298         switch(vid.renderpath)
6299         {
6300         case RENDERPATH_GL20:
6301         case RENDERPATH_CGGL:
6302                 break;
6303         case RENDERPATH_GL13:
6304         case RENDERPATH_GL11:
6305                 wanttangents = false;
6306                 break;
6307         }
6308
6309         // TODO: thread this
6310         // NOTE: R_PrepareRTLights() also caches entities
6311
6312         for (i = 0;i < r_refdef.scene.numentities;i++)
6313                 if (r_refdef.viewcache.entityvisible[i])
6314                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6315
6316         if (r_shadows.integer)
6317                 for (i = 0;i < r_refdef.scene.numentities;i++)
6318                         if (!r_refdef.viewcache.entityvisible[i])
6319                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6320 }
6321
6322 //==================================================================================
6323
6324 static void R_View_UpdateEntityLighting (void)
6325 {
6326         int i;
6327         entity_render_t *ent;
6328         vec3_t tempdiffusenormal, avg;
6329         vec_t f, fa, fd, fdd;
6330
6331         for (i = 0;i < r_refdef.scene.numentities;i++)
6332         {
6333                 ent = r_refdef.scene.entities[i];
6334
6335                 // skip unseen models
6336                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6337                         continue;
6338
6339                 // skip bsp models
6340                 if (ent->model && ent->model->brush.num_leafs)
6341                 {
6342                         // TODO: use modellight for r_ambient settings on world?
6343                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6344                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6345                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6346                         continue;
6347                 }
6348
6349                 // fetch the lighting from the worldmodel data
6350                 VectorClear(ent->modellight_ambient);
6351                 VectorClear(ent->modellight_diffuse);
6352                 VectorClear(tempdiffusenormal);
6353                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6354                 {
6355                         vec3_t org;
6356                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6357                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6358                         if(ent->flags & RENDER_EQUALIZE)
6359                         {
6360                                 // first fix up ambient lighting...
6361                                 if(r_equalize_entities_minambient.value > 0)
6362                                 {
6363                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6364                                         if(fd > 0)
6365                                         {
6366                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6367                                                 if(fa < r_equalize_entities_minambient.value * fd)
6368                                                 {
6369                                                         // solve:
6370                                                         //   fa'/fd' = minambient
6371                                                         //   fa'+0.25*fd' = fa+0.25*fd
6372                                                         //   ...
6373                                                         //   fa' = fd' * minambient
6374                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6375                                                         //   ...
6376                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6377                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6378                                                         //   ...
6379                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6380                                                         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
6381                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6382                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6383                                                 }
6384                                         }
6385                                 }
6386
6387                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6388                                 {
6389                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6390                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6391                                         if(f > 0)
6392                                         {
6393                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6394                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6395                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6396                                         }
6397                                 }
6398                         }
6399                 }
6400                 else // highly rare
6401                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6402
6403                 // move the light direction into modelspace coordinates for lighting code
6404                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6405                 if(VectorLength2(ent->modellight_lightdir) == 0)
6406                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6407                 VectorNormalize(ent->modellight_lightdir);
6408         }
6409 }
6410
6411 #define MAX_LINEOFSIGHTTRACES 64
6412
6413 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6414 {
6415         int i;
6416         vec3_t boxmins, boxmaxs;
6417         vec3_t start;
6418         vec3_t end;
6419         dp_model_t *model = r_refdef.scene.worldmodel;
6420
6421         if (!model || !model->brush.TraceLineOfSight)
6422                 return true;
6423
6424         // expand the box a little
6425         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6426         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6427         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6428         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6429         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6430         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6431
6432         // try center
6433         VectorCopy(eye, start);
6434         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6435         if (model->brush.TraceLineOfSight(model, start, end))
6436                 return true;
6437
6438         // try various random positions
6439         for (i = 0;i < numsamples;i++)
6440         {
6441                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6442                 if (model->brush.TraceLineOfSight(model, start, end))
6443                         return true;
6444         }
6445
6446         return false;
6447 }
6448
6449
6450 static void R_View_UpdateEntityVisible (void)
6451 {
6452         int i;
6453         int renderimask;
6454         int samples;
6455         entity_render_t *ent;
6456
6457         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6458         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6459         {
6460                 // worldmodel can check visibility
6461                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6462                 for (i = 0;i < r_refdef.scene.numentities;i++)
6463                 {
6464                         ent = r_refdef.scene.entities[i];
6465                         if (!(ent->flags & renderimask))
6466                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
6467                         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))
6468                                 r_refdef.viewcache.entityvisible[i] = true;
6469                 }
6470                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6471                 {
6472                         for (i = 0;i < r_refdef.scene.numentities;i++)
6473                         {
6474                                 ent = r_refdef.scene.entities[i];
6475                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6476                                 {
6477                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6478                                         if (samples < 0)
6479                                                 continue; // temp entities do pvs only
6480                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6481                                                 ent->last_trace_visibility = realtime;
6482                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6483                                                 r_refdef.viewcache.entityvisible[i] = 0;
6484                                 }
6485                         }
6486                 }
6487         }
6488         else
6489         {
6490                 // no worldmodel or it can't check visibility
6491                 for (i = 0;i < r_refdef.scene.numentities;i++)
6492                 {
6493                         ent = r_refdef.scene.entities[i];
6494                         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));
6495                 }
6496         }
6497 }
6498
6499 /// only used if skyrendermasked, and normally returns false
6500 int R_DrawBrushModelsSky (void)
6501 {
6502         int i, sky;
6503         entity_render_t *ent;
6504
6505         sky = false;
6506         for (i = 0;i < r_refdef.scene.numentities;i++)
6507         {
6508                 if (!r_refdef.viewcache.entityvisible[i])
6509                         continue;
6510                 ent = r_refdef.scene.entities[i];
6511                 if (!ent->model || !ent->model->DrawSky)
6512                         continue;
6513                 ent->model->DrawSky(ent);
6514                 sky = true;
6515         }
6516         return sky;
6517 }
6518
6519 static void R_DrawNoModel(entity_render_t *ent);
6520 static void R_DrawModels(void)
6521 {
6522         int i;
6523         entity_render_t *ent;
6524
6525         for (i = 0;i < r_refdef.scene.numentities;i++)
6526         {
6527                 if (!r_refdef.viewcache.entityvisible[i])
6528                         continue;
6529                 ent = r_refdef.scene.entities[i];
6530                 r_refdef.stats.entities++;
6531                 if (ent->model && ent->model->Draw != NULL)
6532                         ent->model->Draw(ent);
6533                 else
6534                         R_DrawNoModel(ent);
6535         }
6536 }
6537
6538 static void R_DrawModelsDepth(void)
6539 {
6540         int i;
6541         entity_render_t *ent;
6542
6543         for (i = 0;i < r_refdef.scene.numentities;i++)
6544         {
6545                 if (!r_refdef.viewcache.entityvisible[i])
6546                         continue;
6547                 ent = r_refdef.scene.entities[i];
6548                 if (ent->model && ent->model->DrawDepth != NULL)
6549                         ent->model->DrawDepth(ent);
6550         }
6551 }
6552
6553 static void R_DrawModelsDebug(void)
6554 {
6555         int i;
6556         entity_render_t *ent;
6557
6558         for (i = 0;i < r_refdef.scene.numentities;i++)
6559         {
6560                 if (!r_refdef.viewcache.entityvisible[i])
6561                         continue;
6562                 ent = r_refdef.scene.entities[i];
6563                 if (ent->model && ent->model->DrawDebug != NULL)
6564                         ent->model->DrawDebug(ent);
6565         }
6566 }
6567
6568 static void R_DrawModelsAddWaterPlanes(void)
6569 {
6570         int i;
6571         entity_render_t *ent;
6572
6573         for (i = 0;i < r_refdef.scene.numentities;i++)
6574         {
6575                 if (!r_refdef.viewcache.entityvisible[i])
6576                         continue;
6577                 ent = r_refdef.scene.entities[i];
6578                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6579                         ent->model->DrawAddWaterPlanes(ent);
6580         }
6581 }
6582
6583 static void R_View_SetFrustum(void)
6584 {
6585         int i;
6586         double slopex, slopey;
6587         vec3_t forward, left, up, origin;
6588
6589         // we can't trust r_refdef.view.forward and friends in reflected scenes
6590         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6591
6592 #if 0
6593         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6594         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6595         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6596         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6597         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6598         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6599         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6600         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6601         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6602         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6603         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6604         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6605 #endif
6606
6607 #if 0
6608         zNear = r_refdef.nearclip;
6609         nudge = 1.0 - 1.0 / (1<<23);
6610         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6611         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6612         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6613         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6614         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6615         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6616         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6617         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6618 #endif
6619
6620
6621
6622 #if 0
6623         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6624         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6625         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6626         r_refdef.view.frustum[0].dist = m[15] - m[12];
6627
6628         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6629         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6630         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6631         r_refdef.view.frustum[1].dist = m[15] + m[12];
6632
6633         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6634         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6635         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6636         r_refdef.view.frustum[2].dist = m[15] - m[13];
6637
6638         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6639         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6640         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6641         r_refdef.view.frustum[3].dist = m[15] + m[13];
6642
6643         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6644         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6645         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6646         r_refdef.view.frustum[4].dist = m[15] - m[14];
6647
6648         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6649         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6650         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6651         r_refdef.view.frustum[5].dist = m[15] + m[14];
6652 #endif
6653
6654         if (r_refdef.view.useperspective)
6655         {
6656                 slopex = 1.0 / r_refdef.view.frustum_x;
6657                 slopey = 1.0 / r_refdef.view.frustum_y;
6658                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6659                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6660                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6661                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6662                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6663
6664                 // Leaving those out was a mistake, those were in the old code, and they
6665                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6666                 // I couldn't reproduce it after adding those normalizations. --blub
6667                 VectorNormalize(r_refdef.view.frustum[0].normal);
6668                 VectorNormalize(r_refdef.view.frustum[1].normal);
6669                 VectorNormalize(r_refdef.view.frustum[2].normal);
6670                 VectorNormalize(r_refdef.view.frustum[3].normal);
6671
6672                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6673                 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]);
6674                 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]);
6675                 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]);
6676                 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]);
6677
6678                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6679                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6680                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6681                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6682                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6683         }
6684         else
6685         {
6686                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6687                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6688                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6689                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6690                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6691                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6692                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6693                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6694                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6695                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6696         }
6697         r_refdef.view.numfrustumplanes = 5;
6698
6699         if (r_refdef.view.useclipplane)
6700         {
6701                 r_refdef.view.numfrustumplanes = 6;
6702                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6703         }
6704
6705         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6706                 PlaneClassify(r_refdef.view.frustum + i);
6707
6708         // LordHavoc: note to all quake engine coders, Quake had a special case
6709         // for 90 degrees which assumed a square view (wrong), so I removed it,
6710         // Quake2 has it disabled as well.
6711
6712         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6713         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6714         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6715         //PlaneClassify(&frustum[0]);
6716
6717         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6718         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6719         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6720         //PlaneClassify(&frustum[1]);
6721
6722         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6723         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6724         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6725         //PlaneClassify(&frustum[2]);
6726
6727         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6728         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6729         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6730         //PlaneClassify(&frustum[3]);
6731
6732         // nearclip plane
6733         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6734         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6735         //PlaneClassify(&frustum[4]);
6736 }
6737
6738 void R_View_Update(void)
6739 {
6740         R_Main_ResizeViewCache();
6741         R_View_SetFrustum();
6742         R_View_WorldVisibility(r_refdef.view.useclipplane);
6743         R_View_UpdateEntityVisible();
6744         R_View_UpdateEntityLighting();
6745 }
6746
6747 void R_SetupView(qboolean allowwaterclippingplane)
6748 {
6749         const float *customclipplane = NULL;
6750         float plane[4];
6751         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6752         {
6753                 // LordHavoc: couldn't figure out how to make this approach the
6754                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6755                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6756                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6757                         dist = r_refdef.view.clipplane.dist;
6758                 plane[0] = r_refdef.view.clipplane.normal[0];
6759                 plane[1] = r_refdef.view.clipplane.normal[1];
6760                 plane[2] = r_refdef.view.clipplane.normal[2];
6761                 plane[3] = dist;
6762                 customclipplane = plane;
6763         }
6764
6765         if (!r_refdef.view.useperspective)
6766                 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);
6767         else if (vid.stencil && r_useinfinitefarclip.integer)
6768                 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);
6769         else
6770                 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);
6771         R_SetViewport(&r_refdef.view.viewport);
6772 }
6773
6774 void R_EntityMatrix(const matrix4x4_t *matrix)
6775 {
6776         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6777         {
6778                 gl_modelmatrixchanged = false;
6779                 gl_modelmatrix = *matrix;
6780                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6781                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6782                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6783                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6784                 CHECKGLERROR
6785                 switch(vid.renderpath)
6786                 {
6787                 case RENDERPATH_GL20:
6788                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6789                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6790                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6791                         break;
6792                 case RENDERPATH_CGGL:
6793 #ifdef SUPPORTCG
6794                         CHECKCGERROR
6795                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6796                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6797                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6798 #endif
6799                         break;
6800                 case RENDERPATH_GL13:
6801                 case RENDERPATH_GL11:
6802                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6803                         break;
6804                 }
6805         }
6806 }
6807
6808 void R_ResetViewRendering2D(void)
6809 {
6810         r_viewport_t viewport;
6811         DrawQ_Finish();
6812
6813         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6814         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);
6815         R_SetViewport(&viewport);
6816         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6817         GL_Color(1, 1, 1, 1);
6818         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6819         GL_BlendFunc(GL_ONE, GL_ZERO);
6820         GL_AlphaTest(false);
6821         GL_ScissorTest(false);
6822         GL_DepthMask(false);
6823         GL_DepthRange(0, 1);
6824         GL_DepthTest(false);
6825         R_EntityMatrix(&identitymatrix);
6826         R_Mesh_ResetTextureState();
6827         GL_PolygonOffset(0, 0);
6828         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6829         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6830         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6831         qglStencilMask(~0);CHECKGLERROR
6832         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6833         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6834         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6835 }
6836
6837 void R_ResetViewRendering3D(void)
6838 {
6839         DrawQ_Finish();
6840
6841         R_SetupView(true);
6842         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6843         GL_Color(1, 1, 1, 1);
6844         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6845         GL_BlendFunc(GL_ONE, GL_ZERO);
6846         GL_AlphaTest(false);
6847         GL_ScissorTest(true);
6848         GL_DepthMask(true);
6849         GL_DepthRange(0, 1);
6850         GL_DepthTest(true);
6851         R_EntityMatrix(&identitymatrix);
6852         R_Mesh_ResetTextureState();
6853         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6854         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6855         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6856         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6857         qglStencilMask(~0);CHECKGLERROR
6858         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6859         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6860         GL_CullFace(r_refdef.view.cullface_back);
6861 }
6862
6863 void R_RenderScene(void);
6864 void R_RenderWaterPlanes(void);
6865
6866 static void R_Water_StartFrame(void)
6867 {
6868         int i;
6869         int waterwidth, waterheight, texturewidth, textureheight;
6870         r_waterstate_waterplane_t *p;
6871
6872         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6873                 return;
6874
6875         switch(vid.renderpath)
6876         {
6877         case RENDERPATH_GL20:
6878         case RENDERPATH_CGGL:
6879                 break;
6880         case RENDERPATH_GL13:
6881         case RENDERPATH_GL11:
6882                 return;
6883         }
6884
6885         // set waterwidth and waterheight to the water resolution that will be
6886         // used (often less than the screen resolution for faster rendering)
6887         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6888         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6889
6890         // calculate desired texture sizes
6891         // can't use water if the card does not support the texture size
6892         if (!r_water.integer || r_showsurfaces.integer)
6893                 texturewidth = textureheight = waterwidth = waterheight = 0;
6894         else if (vid.support.arb_texture_non_power_of_two)
6895         {
6896                 texturewidth = waterwidth;
6897                 textureheight = waterheight;
6898         }
6899         else
6900         {
6901                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6902                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6903         }
6904
6905         // allocate textures as needed
6906         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6907         {
6908                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6909                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6910                 {
6911                         if (p->texture_refraction)
6912                                 R_FreeTexture(p->texture_refraction);
6913                         p->texture_refraction = NULL;
6914                         if (p->texture_reflection)
6915                                 R_FreeTexture(p->texture_reflection);
6916                         p->texture_reflection = NULL;
6917                 }
6918                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6919                 r_waterstate.texturewidth = texturewidth;
6920                 r_waterstate.textureheight = textureheight;
6921         }
6922
6923         if (r_waterstate.texturewidth)
6924         {
6925                 r_waterstate.enabled = true;
6926
6927                 // when doing a reduced render (HDR) we want to use a smaller area
6928                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6929                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6930
6931                 // set up variables that will be used in shader setup
6932                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6933                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6934                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6935                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6936         }
6937
6938         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6939         r_waterstate.numwaterplanes = 0;
6940 }
6941
6942 void R_Water_AddWaterPlane(msurface_t *surface)
6943 {
6944         int triangleindex, planeindex;
6945         const int *e;
6946         vec3_t vert[3];
6947         vec3_t normal;
6948         vec3_t center;
6949         mplane_t plane;
6950         r_waterstate_waterplane_t *p;
6951         texture_t *t = R_GetCurrentTexture(surface->texture);
6952         // just use the first triangle with a valid normal for any decisions
6953         VectorClear(normal);
6954         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6955         {
6956                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6957                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6958                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6959                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6960                 if (VectorLength2(normal) >= 0.001)
6961                         break;
6962         }
6963
6964         VectorCopy(normal, plane.normal);
6965         VectorNormalize(plane.normal);
6966         plane.dist = DotProduct(vert[0], plane.normal);
6967         PlaneClassify(&plane);
6968         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6969         {
6970                 // skip backfaces (except if nocullface is set)
6971                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6972                         return;
6973                 VectorNegate(plane.normal, plane.normal);
6974                 plane.dist *= -1;
6975                 PlaneClassify(&plane);
6976         }
6977
6978
6979         // find a matching plane if there is one
6980         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6981                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6982                         break;
6983         if (planeindex >= r_waterstate.maxwaterplanes)
6984                 return; // nothing we can do, out of planes
6985
6986         // if this triangle does not fit any known plane rendered this frame, add one
6987         if (planeindex >= r_waterstate.numwaterplanes)
6988         {
6989                 // store the new plane
6990                 r_waterstate.numwaterplanes++;
6991                 p->plane = plane;
6992                 // clear materialflags and pvs
6993                 p->materialflags = 0;
6994                 p->pvsvalid = false;
6995         }
6996         // merge this surface's materialflags into the waterplane
6997         p->materialflags |= t->currentmaterialflags;
6998         // merge this surface's PVS into the waterplane
6999         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7000         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7001          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7002         {
7003                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7004                 p->pvsvalid = true;
7005         }
7006 }
7007
7008 static void R_Water_ProcessPlanes(void)
7009 {
7010         r_refdef_view_t originalview;
7011         r_refdef_view_t myview;
7012         int planeindex;
7013         r_waterstate_waterplane_t *p;
7014
7015         originalview = r_refdef.view;
7016
7017         // make sure enough textures are allocated
7018         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7019         {
7020                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7021                 {
7022                         if (!p->texture_refraction)
7023                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7024                         if (!p->texture_refraction)
7025                                 goto error;
7026                 }
7027
7028                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7029                 {
7030                         if (!p->texture_reflection)
7031                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7032                         if (!p->texture_reflection)
7033                                 goto error;
7034                 }
7035         }
7036
7037         // render views
7038         r_refdef.view = originalview;
7039         r_refdef.view.showdebug = false;
7040         r_refdef.view.width = r_waterstate.waterwidth;
7041         r_refdef.view.height = r_waterstate.waterheight;
7042         r_refdef.view.useclipplane = true;
7043         myview = r_refdef.view;
7044         r_waterstate.renderingscene = true;
7045         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7046         {
7047                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7048                 {
7049                         r_refdef.view = myview;
7050                         // render reflected scene and copy into texture
7051                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7052                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7053                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7054                         r_refdef.view.clipplane = p->plane;
7055                         // reverse the cullface settings for this render
7056                         r_refdef.view.cullface_front = GL_FRONT;
7057                         r_refdef.view.cullface_back = GL_BACK;
7058                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7059                         {
7060                                 r_refdef.view.usecustompvs = true;
7061                                 if (p->pvsvalid)
7062                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7063                                 else
7064                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7065                         }
7066
7067                         R_ResetViewRendering3D();
7068                         R_ClearScreen(r_refdef.fogenabled);
7069                         R_View_Update();
7070                         R_RenderScene();
7071
7072                         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);
7073                 }
7074
7075                 // render the normal view scene and copy into texture
7076                 // (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)
7077                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7078                 {
7079                         r_refdef.view = myview;
7080                         r_refdef.view.clipplane = p->plane;
7081                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7082                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7083                         PlaneClassify(&r_refdef.view.clipplane);
7084
7085                         R_ResetViewRendering3D();
7086                         R_ClearScreen(r_refdef.fogenabled);
7087                         R_View_Update();
7088                         R_RenderScene();
7089
7090                         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);
7091                 }
7092
7093         }
7094         r_waterstate.renderingscene = false;
7095         r_refdef.view = originalview;
7096         R_ResetViewRendering3D();
7097         R_ClearScreen(r_refdef.fogenabled);
7098         R_View_Update();
7099         return;
7100 error:
7101         r_refdef.view = originalview;
7102         r_waterstate.renderingscene = false;
7103         Cvar_SetValueQuick(&r_water, 0);
7104         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7105         return;
7106 }
7107
7108 void R_Bloom_StartFrame(void)
7109 {
7110         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7111
7112         switch(vid.renderpath)
7113         {
7114         case RENDERPATH_GL20:
7115         case RENDERPATH_CGGL:
7116                 break;
7117         case RENDERPATH_GL13:
7118         case RENDERPATH_GL11:
7119                 return;
7120         }
7121
7122         // set bloomwidth and bloomheight to the bloom resolution that will be
7123         // used (often less than the screen resolution for faster rendering)
7124         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7125         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7126         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7127         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7128         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7129
7130         // calculate desired texture sizes
7131         if (vid.support.arb_texture_non_power_of_two)
7132         {
7133                 screentexturewidth = r_refdef.view.width;
7134                 screentextureheight = r_refdef.view.height;
7135                 bloomtexturewidth = r_bloomstate.bloomwidth;
7136                 bloomtextureheight = r_bloomstate.bloomheight;
7137         }
7138         else
7139         {
7140                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7141                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7142                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7143                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7144         }
7145
7146         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))
7147         {
7148                 Cvar_SetValueQuick(&r_hdr, 0);
7149                 Cvar_SetValueQuick(&r_bloom, 0);
7150                 Cvar_SetValueQuick(&r_motionblur, 0);
7151                 Cvar_SetValueQuick(&r_damageblur, 0);
7152         }
7153
7154         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)))
7155                 screentexturewidth = screentextureheight = 0;
7156         if (!r_hdr.integer && !r_bloom.integer)
7157                 bloomtexturewidth = bloomtextureheight = 0;
7158
7159         // allocate textures as needed
7160         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7161         {
7162                 if (r_bloomstate.texture_screen)
7163                         R_FreeTexture(r_bloomstate.texture_screen);
7164                 r_bloomstate.texture_screen = NULL;
7165                 r_bloomstate.screentexturewidth = screentexturewidth;
7166                 r_bloomstate.screentextureheight = screentextureheight;
7167                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7168                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7169         }
7170         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7171         {
7172                 if (r_bloomstate.texture_bloom)
7173                         R_FreeTexture(r_bloomstate.texture_bloom);
7174                 r_bloomstate.texture_bloom = NULL;
7175                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7176                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7177                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7178                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7179         }
7180
7181         // when doing a reduced render (HDR) we want to use a smaller area
7182         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7183         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7184         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7185         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7186         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7187
7188         // set up a texcoord array for the full resolution screen image
7189         // (we have to keep this around to copy back during final render)
7190         r_bloomstate.screentexcoord2f[0] = 0;
7191         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7192         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7193         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7194         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7195         r_bloomstate.screentexcoord2f[5] = 0;
7196         r_bloomstate.screentexcoord2f[6] = 0;
7197         r_bloomstate.screentexcoord2f[7] = 0;
7198
7199         // set up a texcoord array for the reduced resolution bloom image
7200         // (which will be additive blended over the screen image)
7201         r_bloomstate.bloomtexcoord2f[0] = 0;
7202         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7203         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7204         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7205         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7206         r_bloomstate.bloomtexcoord2f[5] = 0;
7207         r_bloomstate.bloomtexcoord2f[6] = 0;
7208         r_bloomstate.bloomtexcoord2f[7] = 0;
7209
7210         if (r_hdr.integer || r_bloom.integer)
7211         {
7212                 r_bloomstate.enabled = true;
7213                 r_bloomstate.hdr = r_hdr.integer != 0;
7214         }
7215
7216         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);
7217 }
7218
7219 void R_Bloom_CopyBloomTexture(float colorscale)
7220 {
7221         r_refdef.stats.bloom++;
7222
7223         // scale down screen texture to the bloom texture size
7224         CHECKGLERROR
7225         R_SetViewport(&r_bloomstate.viewport);
7226         GL_BlendFunc(GL_ONE, GL_ZERO);
7227         GL_Color(colorscale, colorscale, colorscale, 1);
7228         // TODO: optimize with multitexture or GLSL
7229         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7230         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7231         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7232         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7233
7234         // we now have a bloom image in the framebuffer
7235         // copy it into the bloom image texture for later processing
7236         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);
7237         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7238 }
7239
7240 void R_Bloom_CopyHDRTexture(void)
7241 {
7242         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);
7243         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7244 }
7245
7246 void R_Bloom_MakeTexture(void)
7247 {
7248         int x, range, dir;
7249         float xoffset, yoffset, r, brighten;
7250
7251         r_refdef.stats.bloom++;
7252
7253         R_ResetViewRendering2D();
7254         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7255         R_Mesh_ColorPointer(NULL, 0, 0);
7256
7257         // we have a bloom image in the framebuffer
7258         CHECKGLERROR
7259         R_SetViewport(&r_bloomstate.viewport);
7260
7261         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7262         {
7263                 x *= 2;
7264                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7265                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7266                 GL_Color(r, r, r, 1);
7267                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7268                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7269                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7270                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7271
7272                 // copy the vertically blurred bloom view to a texture
7273                 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);
7274                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7275         }
7276
7277         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7278         brighten = r_bloom_brighten.value;
7279         if (r_hdr.integer)
7280                 brighten *= r_hdr_range.value;
7281         brighten = sqrt(brighten);
7282         if(range >= 1)
7283                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7284         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7285         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7286
7287         for (dir = 0;dir < 2;dir++)
7288         {
7289                 // blend on at multiple vertical offsets to achieve a vertical blur
7290                 // TODO: do offset blends using GLSL
7291                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7292                 GL_BlendFunc(GL_ONE, GL_ZERO);
7293                 for (x = -range;x <= range;x++)
7294                 {
7295                         if (!dir){xoffset = 0;yoffset = x;}
7296                         else {xoffset = x;yoffset = 0;}
7297                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7298                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7299                         // compute a texcoord array with the specified x and y offset
7300                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7301                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7302                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7303                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7304                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7305                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7306                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7307                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7308                         // this r value looks like a 'dot' particle, fading sharply to
7309                         // black at the edges
7310                         // (probably not realistic but looks good enough)
7311                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7312                         //r = brighten/(range*2+1);
7313                         r = brighten / (range * 2 + 1);
7314                         if(range >= 1)
7315                                 r *= (1 - x*x/(float)(range*range));
7316                         GL_Color(r, r, r, 1);
7317                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7318                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7319                         GL_BlendFunc(GL_ONE, GL_ONE);
7320                 }
7321
7322                 // copy the vertically blurred bloom view to a texture
7323                 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);
7324                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7325         }
7326
7327         // apply subtract last
7328         // (just like it would be in a GLSL shader)
7329         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7330         {
7331                 GL_BlendFunc(GL_ONE, GL_ZERO);
7332                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7333                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7334                 GL_Color(1, 1, 1, 1);
7335                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7336                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7337
7338                 GL_BlendFunc(GL_ONE, GL_ONE);
7339                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7340                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7341                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7342                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7343                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7344                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7345                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7346
7347                 // copy the darkened bloom view to a texture
7348                 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);
7349                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7350         }
7351 }
7352
7353 void R_HDR_RenderBloomTexture(void)
7354 {
7355         int oldwidth, oldheight;
7356         float oldcolorscale;
7357
7358         oldcolorscale = r_refdef.view.colorscale;
7359         oldwidth = r_refdef.view.width;
7360         oldheight = r_refdef.view.height;
7361         r_refdef.view.width = r_bloomstate.bloomwidth;
7362         r_refdef.view.height = r_bloomstate.bloomheight;
7363
7364         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7365         // TODO: add exposure compensation features
7366         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7367
7368         r_refdef.view.showdebug = false;
7369         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7370
7371         R_ResetViewRendering3D();
7372
7373         R_ClearScreen(r_refdef.fogenabled);
7374         if (r_timereport_active)
7375                 R_TimeReport("HDRclear");
7376
7377         R_View_Update();
7378         if (r_timereport_active)
7379                 R_TimeReport("visibility");
7380
7381         // only do secondary renders with HDR if r_hdr is 2 or higher
7382         r_waterstate.numwaterplanes = 0;
7383         if (r_waterstate.enabled && r_hdr.integer >= 2)
7384                 R_RenderWaterPlanes();
7385
7386         r_refdef.view.showdebug = true;
7387         R_RenderScene();
7388         r_waterstate.numwaterplanes = 0;
7389
7390         R_ResetViewRendering2D();
7391
7392         R_Bloom_CopyHDRTexture();
7393         R_Bloom_MakeTexture();
7394
7395         // restore the view settings
7396         r_refdef.view.width = oldwidth;
7397         r_refdef.view.height = oldheight;
7398         r_refdef.view.colorscale = oldcolorscale;
7399
7400         R_ResetViewRendering3D();
7401
7402         R_ClearScreen(r_refdef.fogenabled);
7403         if (r_timereport_active)
7404                 R_TimeReport("viewclear");
7405 }
7406
7407 static void R_BlendView(void)
7408 {
7409         unsigned int permutation;
7410         float uservecs[4][4];
7411
7412         switch (vid.renderpath)
7413         {
7414         case RENDERPATH_GL20:
7415         case RENDERPATH_CGGL:
7416                 permutation =
7417                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7418                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7419                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7420                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7421                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7422
7423                 if (r_bloomstate.texture_screen)
7424                 {
7425                         // make sure the buffer is available
7426                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7427
7428                         R_ResetViewRendering2D();
7429                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7430                         R_Mesh_ColorPointer(NULL, 0, 0);
7431
7432                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7433                         {
7434                                 // declare variables
7435                                 float speed;
7436                                 static float avgspeed;
7437
7438                                 speed = VectorLength(cl.movement_velocity);
7439
7440                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7441                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7442
7443                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7444                                 speed = bound(0, speed, 1);
7445                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7446
7447                                 // calculate values into a standard alpha
7448                                 cl.motionbluralpha = 1 - exp(-
7449                                                 (
7450                                                  (r_motionblur.value * speed / 80)
7451                                                  +
7452                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7453                                                 )
7454                                                 /
7455                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7456                                            );
7457
7458                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7459                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7460                                 // apply the blur
7461                                 if (cl.motionbluralpha > 0)
7462                                 {
7463                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7464                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7465                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7466                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7467                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7468                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7469                                 }
7470                         }
7471
7472                         // copy view into the screen texture
7473                         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);
7474                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7475                 }
7476                 else if (!r_bloomstate.texture_bloom)
7477                 {
7478                         // we may still have to do view tint...
7479                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7480                         {
7481                                 // apply a color tint to the whole view
7482                                 R_ResetViewRendering2D();
7483                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7484                                 R_Mesh_ColorPointer(NULL, 0, 0);
7485                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7486                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7487                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7488                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7489                         }
7490                         break; // no screen processing, no bloom, skip it
7491                 }
7492
7493                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7494                 {
7495                         // render simple bloom effect
7496                         // copy the screen and shrink it and darken it for the bloom process
7497                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7498                         // make the bloom texture
7499                         R_Bloom_MakeTexture();
7500                 }
7501
7502 #if _MSC_VER >= 1400
7503 #define sscanf sscanf_s
7504 #endif
7505                 memset(uservecs, 0, sizeof(uservecs));
7506                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7507                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7508                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7509                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7510
7511                 R_ResetViewRendering2D();
7512                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7513                 R_Mesh_ColorPointer(NULL, 0, 0);
7514                 GL_Color(1, 1, 1, 1);
7515                 GL_BlendFunc(GL_ONE, GL_ZERO);
7516                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7517                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7518
7519                 switch(vid.renderpath)
7520                 {
7521                 case RENDERPATH_GL20:
7522                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7523                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7524                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7525                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7526                         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]);
7527                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7528                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7529                         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]);
7530                         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]);
7531                         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]);
7532                         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]);
7533                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7534                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7535                         break;
7536                 case RENDERPATH_CGGL:
7537 #ifdef SUPPORTCG
7538                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7539                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7540                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7541                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7542                         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
7543                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7544                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7545                         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
7546                         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
7547                         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
7548                         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
7549                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7550                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7551 #endif
7552                         break;
7553                 default:
7554                         break;
7555                 }
7556                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7557                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7558                 break;
7559         case RENDERPATH_GL13:
7560         case RENDERPATH_GL11:
7561                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7562                 {
7563                         // apply a color tint to the whole view
7564                         R_ResetViewRendering2D();
7565                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7566                         R_Mesh_ColorPointer(NULL, 0, 0);
7567                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7568                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7569                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7570                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7571                 }
7572                 break;
7573         }
7574 }
7575
7576 matrix4x4_t r_waterscrollmatrix;
7577
7578 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7579 {
7580         if (r_refdef.fog_density)
7581         {
7582                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7583                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7584                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7585
7586                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7587                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7588                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7589                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7590
7591                 {
7592                         vec3_t fogvec;
7593                         VectorCopy(r_refdef.fogcolor, fogvec);
7594                         //   color.rgb *= ContrastBoost * SceneBrightness;
7595                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7596                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7597                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7598                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7599                 }
7600         }
7601 }
7602
7603 void R_UpdateVariables(void)
7604 {
7605         R_Textures_Frame();
7606
7607         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7608
7609         r_refdef.farclip = r_farclip_base.value;
7610         if (r_refdef.scene.worldmodel)
7611                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7612         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7613
7614         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7615                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7616         r_refdef.polygonfactor = 0;
7617         r_refdef.polygonoffset = 0;
7618         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7619         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7620
7621         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7622         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7623         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7624         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7625         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7626         if (r_showsurfaces.integer)
7627         {
7628                 r_refdef.scene.rtworld = false;
7629                 r_refdef.scene.rtworldshadows = false;
7630                 r_refdef.scene.rtdlight = false;
7631                 r_refdef.scene.rtdlightshadows = false;
7632                 r_refdef.lightmapintensity = 0;
7633         }
7634
7635         if (gamemode == GAME_NEHAHRA)
7636         {
7637                 if (gl_fogenable.integer)
7638                 {
7639                         r_refdef.oldgl_fogenable = true;
7640                         r_refdef.fog_density = gl_fogdensity.value;
7641                         r_refdef.fog_red = gl_fogred.value;
7642                         r_refdef.fog_green = gl_foggreen.value;
7643                         r_refdef.fog_blue = gl_fogblue.value;
7644                         r_refdef.fog_alpha = 1;
7645                         r_refdef.fog_start = 0;
7646                         r_refdef.fog_end = gl_skyclip.value;
7647                         r_refdef.fog_height = 1<<30;
7648                         r_refdef.fog_fadedepth = 128;
7649                 }
7650                 else if (r_refdef.oldgl_fogenable)
7651                 {
7652                         r_refdef.oldgl_fogenable = false;
7653                         r_refdef.fog_density = 0;
7654                         r_refdef.fog_red = 0;
7655                         r_refdef.fog_green = 0;
7656                         r_refdef.fog_blue = 0;
7657                         r_refdef.fog_alpha = 0;
7658                         r_refdef.fog_start = 0;
7659                         r_refdef.fog_end = 0;
7660                         r_refdef.fog_height = 1<<30;
7661                         r_refdef.fog_fadedepth = 128;
7662                 }
7663         }
7664
7665         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7666         r_refdef.fog_start = max(0, r_refdef.fog_start);
7667         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7668
7669         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7670
7671         if (r_refdef.fog_density && r_drawfog.integer)
7672         {
7673                 r_refdef.fogenabled = true;
7674                 // this is the point where the fog reaches 0.9986 alpha, which we
7675                 // consider a good enough cutoff point for the texture
7676                 // (0.9986 * 256 == 255.6)
7677                 if (r_fog_exp2.integer)
7678                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7679                 else
7680                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7681                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7682                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7683                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7684                 // fog color was already set
7685                 // update the fog texture
7686                 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)
7687                         R_BuildFogTexture();
7688         }
7689         else
7690                 r_refdef.fogenabled = false;
7691
7692         switch(vid.renderpath)
7693         {
7694         case RENDERPATH_GL20:
7695         case RENDERPATH_CGGL:
7696                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7697                 {
7698                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7699                         {
7700                                 // build GLSL gamma texture
7701 #define RAMPWIDTH 256
7702                                 unsigned short ramp[RAMPWIDTH * 3];
7703                                 unsigned char rampbgr[RAMPWIDTH][4];
7704                                 int i;
7705
7706                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7707
7708                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7709                                 for(i = 0; i < RAMPWIDTH; ++i)
7710                                 {
7711                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7712                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7713                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7714                                         rampbgr[i][3] = 0;
7715                                 }
7716                                 if (r_texture_gammaramps)
7717                                 {
7718                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7719                                 }
7720                                 else
7721                                 {
7722                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
7723                                 }
7724                         }
7725                 }
7726                 else
7727                 {
7728                         // remove GLSL gamma texture
7729                 }
7730                 break;
7731         case RENDERPATH_GL13:
7732         case RENDERPATH_GL11:
7733                 break;
7734         }
7735 }
7736
7737 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7738 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7739 /*
7740 ================
7741 R_SelectScene
7742 ================
7743 */
7744 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7745         if( scenetype != r_currentscenetype ) {
7746                 // store the old scenetype
7747                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7748                 r_currentscenetype = scenetype;
7749                 // move in the new scene
7750                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7751         }
7752 }
7753
7754 /*
7755 ================
7756 R_GetScenePointer
7757 ================
7758 */
7759 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7760 {
7761         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7762         if( scenetype == r_currentscenetype ) {
7763                 return &r_refdef.scene;
7764         } else {
7765                 return &r_scenes_store[ scenetype ];
7766         }
7767 }
7768
7769 /*
7770 ================
7771 R_RenderView
7772 ================
7773 */
7774 void R_RenderView(void)
7775 {
7776         if (r_timereport_active)
7777                 R_TimeReport("start");
7778         r_textureframe++; // used only by R_GetCurrentTexture
7779         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7780
7781         if (!r_drawentities.integer)
7782                 r_refdef.scene.numentities = 0;
7783
7784         R_AnimCache_ClearCache();
7785         R_FrameData_NewFrame();
7786
7787         if (r_refdef.view.isoverlay)
7788         {
7789                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7790                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7791                 R_TimeReport("depthclear");
7792
7793                 r_refdef.view.showdebug = false;
7794
7795                 r_waterstate.enabled = false;
7796                 r_waterstate.numwaterplanes = 0;
7797
7798                 R_RenderScene();
7799
7800                 CHECKGLERROR
7801                 return;
7802         }
7803
7804         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7805                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7806
7807         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7808
7809         // break apart the view matrix into vectors for various purposes
7810         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7811         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7812         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7813         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7814         // make an inverted copy of the view matrix for tracking sprites
7815         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7816
7817         R_Shadow_UpdateWorldLightSelection();
7818
7819         R_Bloom_StartFrame();
7820         R_Water_StartFrame();
7821
7822         CHECKGLERROR
7823         if (r_timereport_active)
7824                 R_TimeReport("viewsetup");
7825
7826         R_ResetViewRendering3D();
7827
7828         if (r_refdef.view.clear || r_refdef.fogenabled)
7829         {
7830                 R_ClearScreen(r_refdef.fogenabled);
7831                 if (r_timereport_active)
7832                         R_TimeReport("viewclear");
7833         }
7834         r_refdef.view.clear = true;
7835
7836         // this produces a bloom texture to be used in R_BlendView() later
7837         if (r_hdr.integer && r_bloomstate.bloomwidth)
7838         {
7839                 R_HDR_RenderBloomTexture();
7840                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
7841                 r_textureframe++; // used only by R_GetCurrentTexture
7842         }
7843
7844         r_refdef.view.showdebug = true;
7845
7846         R_View_Update();
7847         if (r_timereport_active)
7848                 R_TimeReport("visibility");
7849
7850         r_waterstate.numwaterplanes = 0;
7851         if (r_waterstate.enabled)
7852                 R_RenderWaterPlanes();
7853
7854         R_RenderScene();
7855         r_waterstate.numwaterplanes = 0;
7856
7857         R_BlendView();
7858         if (r_timereport_active)
7859                 R_TimeReport("blendview");
7860
7861         GL_Scissor(0, 0, vid.width, vid.height);
7862         GL_ScissorTest(false);
7863         CHECKGLERROR
7864 }
7865
7866 void R_RenderWaterPlanes(void)
7867 {
7868         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7869         {
7870                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7871                 if (r_timereport_active)
7872                         R_TimeReport("waterworld");
7873         }
7874
7875         // don't let sound skip if going slow
7876         if (r_refdef.scene.extraupdate)
7877                 S_ExtraUpdate ();
7878
7879         R_DrawModelsAddWaterPlanes();
7880         if (r_timereport_active)
7881                 R_TimeReport("watermodels");
7882
7883         if (r_waterstate.numwaterplanes)
7884         {
7885                 R_Water_ProcessPlanes();
7886                 if (r_timereport_active)
7887                         R_TimeReport("waterscenes");
7888         }
7889 }
7890
7891 extern void R_DrawLightningBeams (void);
7892 extern void VM_CL_AddPolygonsToMeshQueue (void);
7893 extern void R_DrawPortals (void);
7894 extern cvar_t cl_locs_show;
7895 static void R_DrawLocs(void);
7896 static void R_DrawEntityBBoxes(void);
7897 static void R_DrawModelDecals(void);
7898 extern cvar_t cl_decals_newsystem;
7899 extern qboolean r_shadow_usingdeferredprepass;
7900 void R_RenderScene(void)
7901 {
7902         r_refdef.stats.renders++;
7903
7904         R_UpdateFogColor();
7905
7906         // don't let sound skip if going slow
7907         if (r_refdef.scene.extraupdate)
7908                 S_ExtraUpdate ();
7909
7910         R_MeshQueue_BeginScene();
7911
7912         R_SkyStartFrame();
7913
7914         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);
7915
7916         if (cl.csqc_vidvars.drawworld)
7917         {
7918                 // don't let sound skip if going slow
7919                 if (r_refdef.scene.extraupdate)
7920                         S_ExtraUpdate ();
7921
7922                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7923                 {
7924                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7925                         if (r_timereport_active)
7926                                 R_TimeReport("worldsky");
7927                 }
7928
7929                 if (R_DrawBrushModelsSky() && r_timereport_active)
7930                         R_TimeReport("bmodelsky");
7931
7932                 if (skyrendermasked && skyrenderlater)
7933                 {
7934                         // we have to force off the water clipping plane while rendering sky
7935                         R_SetupView(false);
7936                         R_Sky();
7937                         R_SetupView(true);
7938                         if (r_timereport_active)
7939                                 R_TimeReport("sky");
7940                 }
7941         }
7942
7943         R_AnimCache_CacheVisibleEntities();
7944         if (r_timereport_active)
7945                 R_TimeReport("animation");
7946
7947         R_Shadow_PrepareLights();
7948         if (r_timereport_active)
7949                 R_TimeReport("preparelights");
7950
7951         if (r_shadow_usingdeferredprepass)
7952                 R_Shadow_DrawPrepass();
7953
7954         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7955         {
7956                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7957                 if (r_timereport_active)
7958                         R_TimeReport("worlddepth");
7959         }
7960         if (r_depthfirst.integer >= 2)
7961         {
7962                 R_DrawModelsDepth();
7963                 if (r_timereport_active)
7964                         R_TimeReport("modeldepth");
7965         }
7966
7967         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7968         {
7969                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7970                 if (r_timereport_active)
7971                         R_TimeReport("world");
7972         }
7973
7974         // don't let sound skip if going slow
7975         if (r_refdef.scene.extraupdate)
7976                 S_ExtraUpdate ();
7977
7978         R_DrawModels();
7979         if (r_timereport_active)
7980                 R_TimeReport("models");
7981
7982         // don't let sound skip if going slow
7983         if (r_refdef.scene.extraupdate)
7984                 S_ExtraUpdate ();
7985
7986         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7987         {
7988                 R_DrawModelShadows();
7989                 R_ResetViewRendering3D();
7990                 // don't let sound skip if going slow
7991                 if (r_refdef.scene.extraupdate)
7992                         S_ExtraUpdate ();
7993         }
7994
7995         if (!r_shadow_usingdeferredprepass)
7996         {
7997                 R_Shadow_DrawLights();
7998                 if (r_timereport_active)
7999                         R_TimeReport("rtlights");
8000         }
8001
8002         // don't let sound skip if going slow
8003         if (r_refdef.scene.extraupdate)
8004                 S_ExtraUpdate ();
8005
8006         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8007         {
8008                 R_DrawModelShadows();
8009                 R_ResetViewRendering3D();
8010                 // don't let sound skip if going slow
8011                 if (r_refdef.scene.extraupdate)
8012                         S_ExtraUpdate ();
8013         }
8014
8015         if (cl.csqc_vidvars.drawworld)
8016         {
8017                 if (cl_decals_newsystem.integer)
8018                 {
8019                         R_DrawModelDecals();
8020                         if (r_timereport_active)
8021                                 R_TimeReport("modeldecals");
8022                 }
8023                 else
8024                 {
8025                         R_DrawDecals();
8026                         if (r_timereport_active)
8027                                 R_TimeReport("decals");
8028                 }
8029
8030                 R_DrawParticles();
8031                 if (r_timereport_active)
8032                         R_TimeReport("particles");
8033
8034                 R_DrawExplosions();
8035                 if (r_timereport_active)
8036                         R_TimeReport("explosions");
8037
8038                 R_DrawLightningBeams();
8039                 if (r_timereport_active)
8040                         R_TimeReport("lightning");
8041         }
8042
8043         VM_CL_AddPolygonsToMeshQueue();
8044
8045         if (r_refdef.view.showdebug)
8046         {
8047                 if (cl_locs_show.integer)
8048                 {
8049                         R_DrawLocs();
8050                         if (r_timereport_active)
8051                                 R_TimeReport("showlocs");
8052                 }
8053
8054                 if (r_drawportals.integer)
8055                 {
8056                         R_DrawPortals();
8057                         if (r_timereport_active)
8058                                 R_TimeReport("portals");
8059                 }
8060
8061                 if (r_showbboxes.value > 0)
8062                 {
8063                         R_DrawEntityBBoxes();
8064                         if (r_timereport_active)
8065                                 R_TimeReport("bboxes");
8066                 }
8067         }
8068
8069         R_MeshQueue_RenderTransparent();
8070         if (r_timereport_active)
8071                 R_TimeReport("drawtrans");
8072
8073         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))
8074         {
8075                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8076                 if (r_timereport_active)
8077                         R_TimeReport("worlddebug");
8078                 R_DrawModelsDebug();
8079                 if (r_timereport_active)
8080                         R_TimeReport("modeldebug");
8081         }
8082
8083         if (cl.csqc_vidvars.drawworld)
8084         {
8085                 R_Shadow_DrawCoronas();
8086                 if (r_timereport_active)
8087                         R_TimeReport("coronas");
8088         }
8089
8090         // don't let sound skip if going slow
8091         if (r_refdef.scene.extraupdate)
8092                 S_ExtraUpdate ();
8093
8094         R_ResetViewRendering2D();
8095 }
8096
8097 static const unsigned short bboxelements[36] =
8098 {
8099         5, 1, 3, 5, 3, 7,
8100         6, 2, 0, 6, 0, 4,
8101         7, 3, 2, 7, 2, 6,
8102         4, 0, 1, 4, 1, 5,
8103         4, 5, 7, 4, 7, 6,
8104         1, 0, 2, 1, 2, 3,
8105 };
8106
8107 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8108 {
8109         int i;
8110         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8111
8112         RSurf_ActiveWorldEntity();
8113
8114         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8115         GL_DepthMask(false);
8116         GL_DepthRange(0, 1);
8117         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8118         R_Mesh_ResetTextureState();
8119
8120         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8121         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8122         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8123         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8124         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8125         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8126         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8127         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8128         R_FillColors(color4f, 8, cr, cg, cb, ca);
8129         if (r_refdef.fogenabled)
8130         {
8131                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8132                 {
8133                         f1 = RSurf_FogVertex(v);
8134                         f2 = 1 - f1;
8135                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8136                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8137                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8138                 }
8139         }
8140         R_Mesh_VertexPointer(vertex3f, 0, 0);
8141         R_Mesh_ColorPointer(color4f, 0, 0);
8142         R_Mesh_ResetTextureState();
8143         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8144         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8145 }
8146
8147 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8148 {
8149         int i;
8150         float color[4];
8151         prvm_edict_t *edict;
8152         prvm_prog_t *prog_save = prog;
8153
8154         // this function draws bounding boxes of server entities
8155         if (!sv.active)
8156                 return;
8157
8158         GL_CullFace(GL_NONE);
8159         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8160
8161         prog = 0;
8162         SV_VM_Begin();
8163         for (i = 0;i < numsurfaces;i++)
8164         {
8165                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8166                 switch ((int)edict->fields.server->solid)
8167                 {
8168                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8169                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8170                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8171                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8172                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8173                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8174                 }
8175                 color[3] *= r_showbboxes.value;
8176                 color[3] = bound(0, color[3], 1);
8177                 GL_DepthTest(!r_showdisabledepthtest.integer);
8178                 GL_CullFace(r_refdef.view.cullface_front);
8179                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8180         }
8181         SV_VM_End();
8182         prog = prog_save;
8183 }
8184
8185 static void R_DrawEntityBBoxes(void)
8186 {
8187         int i;
8188         prvm_edict_t *edict;
8189         vec3_t center;
8190         prvm_prog_t *prog_save = prog;
8191
8192         // this function draws bounding boxes of server entities
8193         if (!sv.active)
8194                 return;
8195
8196         prog = 0;
8197         SV_VM_Begin();
8198         for (i = 0;i < prog->num_edicts;i++)
8199         {
8200                 edict = PRVM_EDICT_NUM(i);
8201                 if (edict->priv.server->free)
8202                         continue;
8203                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8204                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8205                         continue;
8206                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8207                         continue;
8208                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8209                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8210         }
8211         SV_VM_End();
8212         prog = prog_save;
8213 }
8214
8215 static const int nomodelelement3i[24] =
8216 {
8217         5, 2, 0,
8218         5, 1, 2,
8219         5, 0, 3,
8220         5, 3, 1,
8221         0, 2, 4,
8222         2, 1, 4,
8223         3, 0, 4,
8224         1, 3, 4
8225 };
8226
8227 static const unsigned short nomodelelement3s[24] =
8228 {
8229         5, 2, 0,
8230         5, 1, 2,
8231         5, 0, 3,
8232         5, 3, 1,
8233         0, 2, 4,
8234         2, 1, 4,
8235         3, 0, 4,
8236         1, 3, 4
8237 };
8238
8239 static const float nomodelvertex3f[6*3] =
8240 {
8241         -16,   0,   0,
8242          16,   0,   0,
8243           0, -16,   0,
8244           0,  16,   0,
8245           0,   0, -16,
8246           0,   0,  16
8247 };
8248
8249 static const float nomodelcolor4f[6*4] =
8250 {
8251         0.0f, 0.0f, 0.5f, 1.0f,
8252         0.0f, 0.0f, 0.5f, 1.0f,
8253         0.0f, 0.5f, 0.0f, 1.0f,
8254         0.0f, 0.5f, 0.0f, 1.0f,
8255         0.5f, 0.0f, 0.0f, 1.0f,
8256         0.5f, 0.0f, 0.0f, 1.0f
8257 };
8258
8259 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8260 {
8261         int i;
8262         float f1, f2, *c;
8263         float color4f[6*4];
8264
8265         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);
8266
8267         // this is only called once per entity so numsurfaces is always 1, and
8268         // surfacelist is always {0}, so this code does not handle batches
8269
8270         if (rsurface.ent_flags & RENDER_ADDITIVE)
8271         {
8272                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8273                 GL_DepthMask(false);
8274         }
8275         else if (rsurface.colormod[3] < 1)
8276         {
8277                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8278                 GL_DepthMask(false);
8279         }
8280         else
8281         {
8282                 GL_BlendFunc(GL_ONE, GL_ZERO);
8283                 GL_DepthMask(true);
8284         }
8285         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8286         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8287         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8288         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8289         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8290         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8291         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8292         R_Mesh_ColorPointer(color4f, 0, 0);
8293         for (i = 0, c = color4f;i < 6;i++, c += 4)
8294         {
8295                 c[0] *= rsurface.colormod[0];
8296                 c[1] *= rsurface.colormod[1];
8297                 c[2] *= rsurface.colormod[2];
8298                 c[3] *= rsurface.colormod[3];
8299         }
8300         if (r_refdef.fogenabled)
8301         {
8302                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8303                 {
8304                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8305                         f2 = 1 - f1;
8306                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8307                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8308                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8309                 }
8310         }
8311         R_Mesh_ResetTextureState();
8312         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8313 }
8314
8315 void R_DrawNoModel(entity_render_t *ent)
8316 {
8317         vec3_t org;
8318         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8319         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8320                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8321         else
8322                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8323 }
8324
8325 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8326 {
8327         vec3_t right1, right2, diff, normal;
8328
8329         VectorSubtract (org2, org1, normal);
8330
8331         // calculate 'right' vector for start
8332         VectorSubtract (r_refdef.view.origin, org1, diff);
8333         CrossProduct (normal, diff, right1);
8334         VectorNormalize (right1);
8335
8336         // calculate 'right' vector for end
8337         VectorSubtract (r_refdef.view.origin, org2, diff);
8338         CrossProduct (normal, diff, right2);
8339         VectorNormalize (right2);
8340
8341         vert[ 0] = org1[0] + width * right1[0];
8342         vert[ 1] = org1[1] + width * right1[1];
8343         vert[ 2] = org1[2] + width * right1[2];
8344         vert[ 3] = org1[0] - width * right1[0];
8345         vert[ 4] = org1[1] - width * right1[1];
8346         vert[ 5] = org1[2] - width * right1[2];
8347         vert[ 6] = org2[0] - width * right2[0];
8348         vert[ 7] = org2[1] - width * right2[1];
8349         vert[ 8] = org2[2] - width * right2[2];
8350         vert[ 9] = org2[0] + width * right2[0];
8351         vert[10] = org2[1] + width * right2[1];
8352         vert[11] = org2[2] + width * right2[2];
8353 }
8354
8355 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)
8356 {
8357         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8358         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8359         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8360         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8361         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8362         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8363         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8364         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8365         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8366         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8367         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8368         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8369 }
8370
8371 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8372 {
8373         int i;
8374         float *vertex3f;
8375         float v[3];
8376         VectorSet(v, x, y, z);
8377         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8378                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8379                         break;
8380         if (i == mesh->numvertices)
8381         {
8382                 if (mesh->numvertices < mesh->maxvertices)
8383                 {
8384                         VectorCopy(v, vertex3f);
8385                         mesh->numvertices++;
8386                 }
8387                 return mesh->numvertices;
8388         }
8389         else
8390                 return i;
8391 }
8392
8393 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8394 {
8395         int i;
8396         int *e, element[3];
8397         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8398         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8399         e = mesh->element3i + mesh->numtriangles * 3;
8400         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8401         {
8402                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8403                 if (mesh->numtriangles < mesh->maxtriangles)
8404                 {
8405                         *e++ = element[0];
8406                         *e++ = element[1];
8407                         *e++ = element[2];
8408                         mesh->numtriangles++;
8409                 }
8410                 element[1] = element[2];
8411         }
8412 }
8413
8414 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8415 {
8416         int i;
8417         int *e, element[3];
8418         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8419         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8420         e = mesh->element3i + mesh->numtriangles * 3;
8421         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8422         {
8423                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8424                 if (mesh->numtriangles < mesh->maxtriangles)
8425                 {
8426                         *e++ = element[0];
8427                         *e++ = element[1];
8428                         *e++ = element[2];
8429                         mesh->numtriangles++;
8430                 }
8431                 element[1] = element[2];
8432         }
8433 }
8434
8435 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8436 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8437 {
8438         int planenum, planenum2;
8439         int w;
8440         int tempnumpoints;
8441         mplane_t *plane, *plane2;
8442         double maxdist;
8443         double temppoints[2][256*3];
8444         // figure out how large a bounding box we need to properly compute this brush
8445         maxdist = 0;
8446         for (w = 0;w < numplanes;w++)
8447                 maxdist = max(maxdist, fabs(planes[w].dist));
8448         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8449         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8450         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8451         {
8452                 w = 0;
8453                 tempnumpoints = 4;
8454                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8455                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8456                 {
8457                         if (planenum2 == planenum)
8458                                 continue;
8459                         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);
8460                         w = !w;
8461                 }
8462                 if (tempnumpoints < 3)
8463                         continue;
8464                 // generate elements forming a triangle fan for this polygon
8465                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8466         }
8467 }
8468
8469 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)
8470 {
8471         texturelayer_t *layer;
8472         layer = t->currentlayers + t->currentnumlayers++;
8473         layer->type = type;
8474         layer->depthmask = depthmask;
8475         layer->blendfunc1 = blendfunc1;
8476         layer->blendfunc2 = blendfunc2;
8477         layer->texture = texture;
8478         layer->texmatrix = *matrix;
8479         layer->color[0] = r;
8480         layer->color[1] = g;
8481         layer->color[2] = b;
8482         layer->color[3] = a;
8483 }
8484
8485 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8486 {
8487         double index, f;
8488         index = parms[2] + r_refdef.scene.time * parms[3];
8489         index -= floor(index);
8490         switch (func)
8491         {
8492         default:
8493         case Q3WAVEFUNC_NONE:
8494         case Q3WAVEFUNC_NOISE:
8495         case Q3WAVEFUNC_COUNT:
8496                 f = 0;
8497                 break;
8498         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8499         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8500         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8501         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8502         case Q3WAVEFUNC_TRIANGLE:
8503                 index *= 4;
8504                 f = index - floor(index);
8505                 if (index < 1)
8506                         f = f;
8507                 else if (index < 2)
8508                         f = 1 - f;
8509                 else if (index < 3)
8510                         f = -f;
8511                 else
8512                         f = -(1 - f);
8513                 break;
8514         }
8515         return (float)(parms[0] + parms[1] * f);
8516 }
8517
8518 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8519 {
8520         int w, h, idx;
8521         float f;
8522         float tcmat[12];
8523         matrix4x4_t matrix, temp;
8524         switch(tcmod->tcmod)
8525         {
8526                 case Q3TCMOD_COUNT:
8527                 case Q3TCMOD_NONE:
8528                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8529                                 matrix = r_waterscrollmatrix;
8530                         else
8531                                 matrix = identitymatrix;
8532                         break;
8533                 case Q3TCMOD_ENTITYTRANSLATE:
8534                         // this is used in Q3 to allow the gamecode to control texcoord
8535                         // scrolling on the entity, which is not supported in darkplaces yet.
8536                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8537                         break;
8538                 case Q3TCMOD_ROTATE:
8539                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8540                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8541                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8542                         break;
8543                 case Q3TCMOD_SCALE:
8544                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8545                         break;
8546                 case Q3TCMOD_SCROLL:
8547                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8548                         break;
8549                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8550                         w = (int) tcmod->parms[0];
8551                         h = (int) tcmod->parms[1];
8552                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8553                         f = f - floor(f);
8554                         idx = (int) floor(f * w * h);
8555                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8556                         break;
8557                 case Q3TCMOD_STRETCH:
8558                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8559                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8560                         break;
8561                 case Q3TCMOD_TRANSFORM:
8562                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8563                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8564                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8565                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8566                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8567                         break;
8568                 case Q3TCMOD_TURBULENT:
8569                         // this is handled in the RSurf_PrepareVertices function
8570                         matrix = identitymatrix;
8571                         break;
8572         }
8573         temp = *texmatrix;
8574         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8575 }
8576
8577 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8578 {
8579         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8580         char name[MAX_QPATH];
8581         skinframe_t *skinframe;
8582         unsigned char pixels[296*194];
8583         strlcpy(cache->name, skinname, sizeof(cache->name));
8584         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8585         if (developer_loading.integer)
8586                 Con_Printf("loading %s\n", name);
8587         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8588         if (!skinframe || !skinframe->base)
8589         {
8590                 unsigned char *f;
8591                 fs_offset_t filesize;
8592                 skinframe = NULL;
8593                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8594                 if (f)
8595                 {
8596                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8597                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8598                         Mem_Free(f);
8599                 }
8600         }
8601         cache->skinframe = skinframe;
8602 }
8603
8604 texture_t *R_GetCurrentTexture(texture_t *t)
8605 {
8606         int i;
8607         const entity_render_t *ent = rsurface.entity;
8608         dp_model_t *model = ent->model;
8609         q3shaderinfo_layer_tcmod_t *tcmod;
8610
8611         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8612                 return t->currentframe;
8613         t->update_lastrenderframe = r_textureframe;
8614         t->update_lastrenderentity = (void *)ent;
8615
8616         // switch to an alternate material if this is a q1bsp animated material
8617         {
8618                 texture_t *texture = t;
8619                 int s = rsurface.ent_skinnum;
8620                 if ((unsigned int)s >= (unsigned int)model->numskins)
8621                         s = 0;
8622                 if (model->skinscenes)
8623                 {
8624                         if (model->skinscenes[s].framecount > 1)
8625                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8626                         else
8627                                 s = model->skinscenes[s].firstframe;
8628                 }
8629                 if (s > 0)
8630                         t = t + s * model->num_surfaces;
8631                 if (t->animated)
8632                 {
8633                         // use an alternate animation if the entity's frame is not 0,
8634                         // and only if the texture has an alternate animation
8635                         if (rsurface.ent_alttextures && t->anim_total[1])
8636                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8637                         else
8638                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8639                 }
8640                 texture->currentframe = t;
8641         }
8642
8643         // update currentskinframe to be a qw skin or animation frame
8644         if (rsurface.ent_qwskin >= 0)
8645         {
8646                 i = rsurface.ent_qwskin;
8647                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8648                 {
8649                         r_qwskincache_size = cl.maxclients;
8650                         if (r_qwskincache)
8651                                 Mem_Free(r_qwskincache);
8652                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8653                 }
8654                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8655                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8656                 t->currentskinframe = r_qwskincache[i].skinframe;
8657                 if (t->currentskinframe == NULL)
8658                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8659         }
8660         else if (t->numskinframes >= 2)
8661                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8662         if (t->backgroundnumskinframes >= 2)
8663                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8664
8665         t->currentmaterialflags = t->basematerialflags;
8666         t->currentalpha = rsurface.colormod[3];
8667         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8668                 t->currentalpha *= r_wateralpha.value;
8669         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8670                 t->currentalpha *= t->r_water_wateralpha;
8671         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8672                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8673         if (!(rsurface.ent_flags & RENDER_LIGHT))
8674                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8675         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8676         {
8677                 // pick a model lighting mode
8678                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8679                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8680                 else
8681                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8682         }
8683         if (rsurface.ent_flags & RENDER_ADDITIVE)
8684                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8685         else if (t->currentalpha < 1)
8686                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8687         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8688                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8689         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8690                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8691         if (t->backgroundnumskinframes)
8692                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8693         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8694         {
8695                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8696                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8697         }
8698         else
8699                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8700         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8701                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8702
8703         // there is no tcmod
8704         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8705         {
8706                 t->currenttexmatrix = r_waterscrollmatrix;
8707                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8708         }
8709         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8710         {
8711                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8712                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8713         }
8714
8715         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8716                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8717         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8718                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8719
8720         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8721         if (t->currentskinframe->qpixels)
8722                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8723         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8724         if (!t->basetexture)
8725                 t->basetexture = r_texture_notexture;
8726         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8727         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8728         t->nmaptexture = t->currentskinframe->nmap;
8729         if (!t->nmaptexture)
8730                 t->nmaptexture = r_texture_blanknormalmap;
8731         t->glosstexture = r_texture_black;
8732         t->glowtexture = t->currentskinframe->glow;
8733         t->fogtexture = t->currentskinframe->fog;
8734         if (t->backgroundnumskinframes)
8735         {
8736                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8737                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8738                 t->backgroundglosstexture = r_texture_black;
8739                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8740                 if (!t->backgroundnmaptexture)
8741                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8742         }
8743         else
8744         {
8745                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8746                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8747                 t->backgroundglosstexture = r_texture_black;
8748                 t->backgroundglowtexture = NULL;
8749         }
8750         t->specularpower = r_shadow_glossexponent.value;
8751         // TODO: store reference values for these in the texture?
8752         t->specularscale = 0;
8753         if (r_shadow_gloss.integer > 0)
8754         {
8755                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8756                 {
8757                         if (r_shadow_glossintensity.value > 0)
8758                         {
8759                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8760                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8761                                 t->specularscale = r_shadow_glossintensity.value;
8762                         }
8763                 }
8764                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8765                 {
8766                         t->glosstexture = r_texture_white;
8767                         t->backgroundglosstexture = r_texture_white;
8768                         t->specularscale = r_shadow_gloss2intensity.value;
8769                         t->specularpower = r_shadow_gloss2exponent.value;
8770                 }
8771         }
8772         t->specularscale *= t->specularscalemod;
8773         t->specularpower *= t->specularpowermod;
8774
8775         // lightmaps mode looks bad with dlights using actual texturing, so turn
8776         // off the colormap and glossmap, but leave the normalmap on as it still
8777         // accurately represents the shading involved
8778         if (gl_lightmaps.integer)
8779         {
8780                 t->basetexture = r_texture_grey128;
8781                 t->pantstexture = r_texture_black;
8782                 t->shirttexture = r_texture_black;
8783                 t->nmaptexture = r_texture_blanknormalmap;
8784                 t->glosstexture = r_texture_black;
8785                 t->glowtexture = NULL;
8786                 t->fogtexture = NULL;
8787                 t->backgroundbasetexture = NULL;
8788                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8789                 t->backgroundglosstexture = r_texture_black;
8790                 t->backgroundglowtexture = NULL;
8791                 t->specularscale = 0;
8792                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8793         }
8794
8795         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8796         VectorClear(t->dlightcolor);
8797         t->currentnumlayers = 0;
8798         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8799         {
8800                 int blendfunc1, blendfunc2;
8801                 qboolean depthmask;
8802                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8803                 {
8804                         blendfunc1 = GL_SRC_ALPHA;
8805                         blendfunc2 = GL_ONE;
8806                 }
8807                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8808                 {
8809                         blendfunc1 = GL_SRC_ALPHA;
8810                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8811                 }
8812                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8813                 {
8814                         blendfunc1 = t->customblendfunc[0];
8815                         blendfunc2 = t->customblendfunc[1];
8816                 }
8817                 else
8818                 {
8819                         blendfunc1 = GL_ONE;
8820                         blendfunc2 = GL_ZERO;
8821                 }
8822                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8823                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8824                 {
8825                         // fullbright is not affected by r_refdef.lightmapintensity
8826                         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]);
8827                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8828                                 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]);
8829                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8830                                 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]);
8831                 }
8832                 else
8833                 {
8834                         vec3_t ambientcolor;
8835                         float colorscale;
8836                         // set the color tint used for lights affecting this surface
8837                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8838                         colorscale = 2;
8839                         // q3bsp has no lightmap updates, so the lightstylevalue that
8840                         // would normally be baked into the lightmap must be
8841                         // applied to the color
8842                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8843                         if (model->type == mod_brushq3)
8844                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8845                         colorscale *= r_refdef.lightmapintensity;
8846                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8847                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8848                         // basic lit geometry
8849                         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]);
8850                         // add pants/shirt if needed
8851                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8852                                 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]);
8853                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8854                                 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]);
8855                         // now add ambient passes if needed
8856                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8857                         {
8858                                 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]);
8859                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8860                                         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]);
8861                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8862                                         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]);
8863                         }
8864                 }
8865                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8866                         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]);
8867                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8868                 {
8869                         // if this is opaque use alpha blend which will darken the earlier
8870                         // passes cheaply.
8871                         //
8872                         // if this is an alpha blended material, all the earlier passes
8873                         // were darkened by fog already, so we only need to add the fog
8874                         // color ontop through the fog mask texture
8875                         //
8876                         // if this is an additive blended material, all the earlier passes
8877                         // were darkened by fog already, and we should not add fog color
8878                         // (because the background was not darkened, there is no fog color
8879                         // that was lost behind it).
8880                         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]);
8881                 }
8882         }
8883
8884         return t->currentframe;
8885 }
8886
8887 rsurfacestate_t rsurface;
8888
8889 void R_Mesh_ResizeArrays(int newvertices)
8890 {
8891         float *base;
8892         if (rsurface.array_size >= newvertices)
8893                 return;
8894         if (rsurface.array_modelvertex3f)
8895                 Mem_Free(rsurface.array_modelvertex3f);
8896         rsurface.array_size = (newvertices + 1023) & ~1023;
8897         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8898         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8899         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8900         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8901         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8902         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8903         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8904         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8905         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8906         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8907         rsurface.array_color4f           = base + rsurface.array_size * 27;
8908         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8909 }
8910
8911 void RSurf_ActiveWorldEntity(void)
8912 {
8913         dp_model_t *model = r_refdef.scene.worldmodel;
8914         //if (rsurface.entity == r_refdef.scene.worldentity)
8915         //      return;
8916         rsurface.entity = r_refdef.scene.worldentity;
8917         rsurface.skeleton = NULL;
8918         rsurface.ent_skinnum = 0;
8919         rsurface.ent_qwskin = -1;
8920         rsurface.ent_shadertime = 0;
8921         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8922         if (rsurface.array_size < model->surfmesh.num_vertices)
8923                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8924         rsurface.matrix = identitymatrix;
8925         rsurface.inversematrix = identitymatrix;
8926         rsurface.matrixscale = 1;
8927         rsurface.inversematrixscale = 1;
8928         R_EntityMatrix(&identitymatrix);
8929         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8930         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8931         rsurface.fograngerecip = r_refdef.fograngerecip;
8932         rsurface.fogheightfade = r_refdef.fogheightfade;
8933         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8934         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8935         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8936         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8937         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8938         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8939         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8940         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8941         rsurface.colormod[3] = 1;
8942         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);
8943         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8944         rsurface.frameblend[0].lerp = 1;
8945         rsurface.ent_alttextures = false;
8946         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8947         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8948         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8949         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8950         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8951         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8952         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8953         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8954         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8955         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8956         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8957         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8958         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8959         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8960         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8961         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8962         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8963         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8964         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8965         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8966         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8967         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8968         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8969         rsurface.modelelement3i = model->surfmesh.data_element3i;
8970         rsurface.modelelement3s = model->surfmesh.data_element3s;
8971         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8972         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8973         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8974         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8975         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8976         rsurface.modelsurfaces = model->data_surfaces;
8977         rsurface.generatedvertex = false;
8978         rsurface.vertex3f  = rsurface.modelvertex3f;
8979         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8980         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8981         rsurface.svector3f = rsurface.modelsvector3f;
8982         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8983         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8984         rsurface.tvector3f = rsurface.modeltvector3f;
8985         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8986         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8987         rsurface.normal3f  = rsurface.modelnormal3f;
8988         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8989         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8990         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8991 }
8992
8993 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8994 {
8995         dp_model_t *model = ent->model;
8996         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8997         //      return;
8998         rsurface.entity = (entity_render_t *)ent;
8999         rsurface.skeleton = ent->skeleton;
9000         rsurface.ent_skinnum = ent->skinnum;
9001         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;
9002         rsurface.ent_shadertime = ent->shadertime;
9003         rsurface.ent_flags = ent->flags;
9004         if (rsurface.array_size < model->surfmesh.num_vertices)
9005                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9006         rsurface.matrix = ent->matrix;
9007         rsurface.inversematrix = ent->inversematrix;
9008         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9009         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9010         R_EntityMatrix(&rsurface.matrix);
9011         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9012         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9013         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9014         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9015         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9016         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9017         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9018         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9019         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9020         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9021         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9022         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9023         rsurface.colormod[3] = ent->alpha;
9024         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9025         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9026         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9027         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9028         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9029         if (ent->model->brush.submodel && !prepass)
9030         {
9031                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9032                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9033         }
9034         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9035         {
9036                 if (ent->animcache_vertex3f && !r_framedata_failed)
9037                 {
9038                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9039                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9040                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9041                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9042                 }
9043                 else if (wanttangents)
9044                 {
9045                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9046                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9047                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9048                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9049                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9050                 }
9051                 else if (wantnormals)
9052                 {
9053                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9054                         rsurface.modelsvector3f = NULL;
9055                         rsurface.modeltvector3f = NULL;
9056                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9057                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9058                 }
9059                 else
9060                 {
9061                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9062                         rsurface.modelsvector3f = NULL;
9063                         rsurface.modeltvector3f = NULL;
9064                         rsurface.modelnormal3f = NULL;
9065                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9066                 }
9067                 rsurface.modelvertex3f_bufferobject = 0;
9068                 rsurface.modelvertex3f_bufferoffset = 0;
9069                 rsurface.modelsvector3f_bufferobject = 0;
9070                 rsurface.modelsvector3f_bufferoffset = 0;
9071                 rsurface.modeltvector3f_bufferobject = 0;
9072                 rsurface.modeltvector3f_bufferoffset = 0;
9073                 rsurface.modelnormal3f_bufferobject = 0;
9074                 rsurface.modelnormal3f_bufferoffset = 0;
9075                 rsurface.generatedvertex = true;
9076         }
9077         else
9078         {
9079                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9080                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9081                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9082                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9083                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9084                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9085                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9086                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9087                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9088                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9089                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9090                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9091                 rsurface.generatedvertex = false;
9092         }
9093         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9094         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9095         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9096         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9097         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9098         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9099         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9100         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9101         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9102         rsurface.modelelement3i = model->surfmesh.data_element3i;
9103         rsurface.modelelement3s = model->surfmesh.data_element3s;
9104         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9105         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9106         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9107         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9108         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9109         rsurface.modelsurfaces = model->data_surfaces;
9110         rsurface.vertex3f  = rsurface.modelvertex3f;
9111         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9112         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9113         rsurface.svector3f = rsurface.modelsvector3f;
9114         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9115         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9116         rsurface.tvector3f = rsurface.modeltvector3f;
9117         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9118         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9119         rsurface.normal3f  = rsurface.modelnormal3f;
9120         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9121         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9122         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9123 }
9124
9125 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)
9126 {
9127         rsurface.entity = r_refdef.scene.worldentity;
9128         rsurface.skeleton = NULL;
9129         rsurface.ent_skinnum = 0;
9130         rsurface.ent_qwskin = -1;
9131         rsurface.ent_shadertime = shadertime;
9132         rsurface.ent_flags = entflags;
9133         rsurface.modelnum_vertices = numvertices;
9134         rsurface.modelnum_triangles = numtriangles;
9135         if (rsurface.array_size < rsurface.modelnum_vertices)
9136                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9137         rsurface.matrix = *matrix;
9138         rsurface.inversematrix = *inversematrix;
9139         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9140         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9141         R_EntityMatrix(&rsurface.matrix);
9142         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9143         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9144         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9145         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9146         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9147         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9148         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9149         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9150         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9151         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9152         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9153         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9154         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);
9155         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9156         rsurface.frameblend[0].lerp = 1;
9157         rsurface.ent_alttextures = false;
9158         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9159         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9160         if (wanttangents)
9161         {
9162                 rsurface.modelvertex3f = vertex3f;
9163                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9164                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9165                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9166         }
9167         else if (wantnormals)
9168         {
9169                 rsurface.modelvertex3f = vertex3f;
9170                 rsurface.modelsvector3f = NULL;
9171                 rsurface.modeltvector3f = NULL;
9172                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9173         }
9174         else
9175         {
9176                 rsurface.modelvertex3f = vertex3f;
9177                 rsurface.modelsvector3f = NULL;
9178                 rsurface.modeltvector3f = NULL;
9179                 rsurface.modelnormal3f = NULL;
9180         }
9181         rsurface.modelvertex3f_bufferobject = 0;
9182         rsurface.modelvertex3f_bufferoffset = 0;
9183         rsurface.modelsvector3f_bufferobject = 0;
9184         rsurface.modelsvector3f_bufferoffset = 0;
9185         rsurface.modeltvector3f_bufferobject = 0;
9186         rsurface.modeltvector3f_bufferoffset = 0;
9187         rsurface.modelnormal3f_bufferobject = 0;
9188         rsurface.modelnormal3f_bufferoffset = 0;
9189         rsurface.generatedvertex = true;
9190         rsurface.modellightmapcolor4f  = color4f;
9191         rsurface.modellightmapcolor4f_bufferobject = 0;
9192         rsurface.modellightmapcolor4f_bufferoffset = 0;
9193         rsurface.modeltexcoordtexture2f  = texcoord2f;
9194         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9195         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9196         rsurface.modeltexcoordlightmap2f  = NULL;
9197         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9198         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9199         rsurface.modelelement3i = element3i;
9200         rsurface.modelelement3s = element3s;
9201         rsurface.modelelement3i_bufferobject = 0;
9202         rsurface.modelelement3s_bufferobject = 0;
9203         rsurface.modellightmapoffsets = NULL;
9204         rsurface.modelsurfaces = NULL;
9205         rsurface.vertex3f  = rsurface.modelvertex3f;
9206         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9207         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9208         rsurface.svector3f = rsurface.modelsvector3f;
9209         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9210         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9211         rsurface.tvector3f = rsurface.modeltvector3f;
9212         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9213         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9214         rsurface.normal3f  = rsurface.modelnormal3f;
9215         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9216         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9217         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9218
9219         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9220         {
9221                 if ((wantnormals || wanttangents) && !normal3f)
9222                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9223                 if (wanttangents && !svector3f)
9224                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9225         }
9226 }
9227
9228 float RSurf_FogPoint(const float *v)
9229 {
9230         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9231         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9232         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9233         float FogHeightFade = r_refdef.fogheightfade;
9234         float fogfrac;
9235         unsigned int fogmasktableindex;
9236         if (r_refdef.fogplaneviewabove)
9237                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9238         else
9239                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9240         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9241         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9242 }
9243
9244 float RSurf_FogVertex(const float *v)
9245 {
9246         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9247         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9248         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9249         float FogHeightFade = rsurface.fogheightfade;
9250         float fogfrac;
9251         unsigned int fogmasktableindex;
9252         if (r_refdef.fogplaneviewabove)
9253                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9254         else
9255                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9256         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9257         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9258 }
9259
9260 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9261 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9262 {
9263         int deformindex;
9264         int texturesurfaceindex;
9265         int i, j;
9266         float amplitude;
9267         float animpos;
9268         float scale;
9269         const float *v1, *in_tc;
9270         float *out_tc;
9271         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9272         float waveparms[4];
9273         q3shaderinfo_deform_t *deform;
9274         // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
9275         if (rsurface.generatedvertex)
9276         {
9277                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9278                         generatenormals = true;
9279                 for (i = 0;i < Q3MAXDEFORMS;i++)
9280                 {
9281                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9282                         {
9283                                 generatetangents = true;
9284                                 generatenormals = true;
9285                         }
9286                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9287                                 generatenormals = true;
9288                 }
9289                 if (generatenormals && !rsurface.modelnormal3f)
9290                 {
9291                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9292                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9293                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9294                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9295                 }
9296                 if (generatetangents && !rsurface.modelsvector3f)
9297                 {
9298                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9299                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9300                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9301                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9302                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9303                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9304                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9305                 }
9306         }
9307         rsurface.vertex3f  = rsurface.modelvertex3f;
9308         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9309         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9310         rsurface.svector3f = rsurface.modelsvector3f;
9311         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9312         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9313         rsurface.tvector3f = rsurface.modeltvector3f;
9314         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9315         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9316         rsurface.normal3f  = rsurface.modelnormal3f;
9317         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9318         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9319         // if vertices are deformed (sprite flares and things in maps, possibly
9320         // water waves, bulges and other deformations), generate them into
9321         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9322         // (may be static model data or generated data for an animated model, or
9323         //  the previous deform pass)
9324         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9325         {
9326                 switch (deform->deform)
9327                 {
9328                 default:
9329                 case Q3DEFORM_PROJECTIONSHADOW:
9330                 case Q3DEFORM_TEXT0:
9331                 case Q3DEFORM_TEXT1:
9332                 case Q3DEFORM_TEXT2:
9333                 case Q3DEFORM_TEXT3:
9334                 case Q3DEFORM_TEXT4:
9335                 case Q3DEFORM_TEXT5:
9336                 case Q3DEFORM_TEXT6:
9337                 case Q3DEFORM_TEXT7:
9338                 case Q3DEFORM_NONE:
9339                         break;
9340                 case Q3DEFORM_AUTOSPRITE:
9341                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9342                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9343                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9344                         VectorNormalize(newforward);
9345                         VectorNormalize(newright);
9346                         VectorNormalize(newup);
9347                         // make deformed versions of only the model vertices used by the specified surfaces
9348                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9349                         {
9350                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9351                                 // a single autosprite surface can contain multiple sprites...
9352                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9353                                 {
9354                                         VectorClear(center);
9355                                         for (i = 0;i < 4;i++)
9356                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9357                                         VectorScale(center, 0.25f, center);
9358                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9359                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9360                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9361                                         for (i = 0;i < 4;i++)
9362                                         {
9363                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9364                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9365                                         }
9366                                 }
9367                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9368                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9369                         }
9370                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9371                         rsurface.vertex3f_bufferobject = 0;
9372                         rsurface.vertex3f_bufferoffset = 0;
9373                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9374                         rsurface.svector3f_bufferobject = 0;
9375                         rsurface.svector3f_bufferoffset = 0;
9376                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9377                         rsurface.tvector3f_bufferobject = 0;
9378                         rsurface.tvector3f_bufferoffset = 0;
9379                         rsurface.normal3f = rsurface.array_deformednormal3f;
9380                         rsurface.normal3f_bufferobject = 0;
9381                         rsurface.normal3f_bufferoffset = 0;
9382                         break;
9383                 case Q3DEFORM_AUTOSPRITE2:
9384                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9385                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9386                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9387                         VectorNormalize(newforward);
9388                         VectorNormalize(newright);
9389                         VectorNormalize(newup);
9390                         // make deformed versions of only the model vertices used by the specified surfaces
9391                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9392                         {
9393                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9394                                 const float *v1, *v2;
9395                                 vec3_t start, end;
9396                                 float f, l;
9397                                 struct
9398                                 {
9399                                         float length2;
9400                                         const float *v1;
9401                                         const float *v2;
9402                                 }
9403                                 shortest[2];
9404                                 memset(shortest, 0, sizeof(shortest));
9405                                 // a single autosprite surface can contain multiple sprites...
9406                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9407                                 {
9408                                         VectorClear(center);
9409                                         for (i = 0;i < 4;i++)
9410                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9411                                         VectorScale(center, 0.25f, center);
9412                                         // find the two shortest edges, then use them to define the
9413                                         // axis vectors for rotating around the central axis
9414                                         for (i = 0;i < 6;i++)
9415                                         {
9416                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9417                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9418 #if 0
9419                                                 Debug_PolygonBegin(NULL, 0);
9420                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9421                                                 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
9422                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9423                                                 Debug_PolygonEnd();
9424 #endif
9425                                                 l = VectorDistance2(v1, v2);
9426                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9427                                                 if (v1[2] != v2[2])
9428                                                         l += (1.0f / 1024.0f);
9429                                                 if (shortest[0].length2 > l || i == 0)
9430                                                 {
9431                                                         shortest[1] = shortest[0];
9432                                                         shortest[0].length2 = l;
9433                                                         shortest[0].v1 = v1;
9434                                                         shortest[0].v2 = v2;
9435                                                 }
9436                                                 else if (shortest[1].length2 > l || i == 1)
9437                                                 {
9438                                                         shortest[1].length2 = l;
9439                                                         shortest[1].v1 = v1;
9440                                                         shortest[1].v2 = v2;
9441                                                 }
9442                                         }
9443                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9444                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9445 #if 0
9446                                         Debug_PolygonBegin(NULL, 0);
9447                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9448                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
9449                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9450                                         Debug_PolygonEnd();
9451 #endif
9452                                         // this calculates the right vector from the shortest edge
9453                                         // and the up vector from the edge midpoints
9454                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9455                                         VectorNormalize(right);
9456                                         VectorSubtract(end, start, up);
9457                                         VectorNormalize(up);
9458                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9459                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9460                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9461                                         VectorNegate(forward, forward);
9462                                         VectorReflect(forward, 0, up, forward);
9463                                         VectorNormalize(forward);
9464                                         CrossProduct(up, forward, newright);
9465                                         VectorNormalize(newright);
9466 #if 0
9467                                         Debug_PolygonBegin(NULL, 0);
9468                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
9469                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9470                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9471                                         Debug_PolygonEnd();
9472 #endif
9473 #if 0
9474                                         Debug_PolygonBegin(NULL, 0);
9475                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9476                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9477                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9478                                         Debug_PolygonEnd();
9479 #endif
9480                                         // rotate the quad around the up axis vector, this is made
9481                                         // especially easy by the fact we know the quad is flat,
9482                                         // so we only have to subtract the center position and
9483                                         // measure distance along the right vector, and then
9484                                         // multiply that by the newright vector and add back the
9485                                         // center position
9486                                         // we also need to subtract the old position to undo the
9487                                         // displacement from the center, which we do with a
9488                                         // DotProduct, the subtraction/addition of center is also
9489                                         // optimized into DotProducts here
9490                                         l = DotProduct(right, center);
9491                                         for (i = 0;i < 4;i++)
9492                                         {
9493                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9494                                                 f = DotProduct(right, v1) - l;
9495                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9496                                         }
9497                                 }
9498                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9499                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9500                         }
9501                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9502                         rsurface.vertex3f_bufferobject = 0;
9503                         rsurface.vertex3f_bufferoffset = 0;
9504                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9505                         rsurface.svector3f_bufferobject = 0;
9506                         rsurface.svector3f_bufferoffset = 0;
9507                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9508                         rsurface.tvector3f_bufferobject = 0;
9509                         rsurface.tvector3f_bufferoffset = 0;
9510                         rsurface.normal3f = rsurface.array_deformednormal3f;
9511                         rsurface.normal3f_bufferobject = 0;
9512                         rsurface.normal3f_bufferoffset = 0;
9513                         break;
9514                 case Q3DEFORM_NORMAL:
9515                         // deform the normals to make reflections wavey
9516                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9517                         {
9518                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9519                                 for (j = 0;j < surface->num_vertices;j++)
9520                                 {
9521                                         float vertex[3];
9522                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9523                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9524                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9525                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9526                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9527                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9528                                         VectorNormalize(normal);
9529                                 }
9530                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9531                         }
9532                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9533                         rsurface.svector3f_bufferobject = 0;
9534                         rsurface.svector3f_bufferoffset = 0;
9535                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9536                         rsurface.tvector3f_bufferobject = 0;
9537                         rsurface.tvector3f_bufferoffset = 0;
9538                         rsurface.normal3f = rsurface.array_deformednormal3f;
9539                         rsurface.normal3f_bufferobject = 0;
9540                         rsurface.normal3f_bufferoffset = 0;
9541                         break;
9542                 case Q3DEFORM_WAVE:
9543                         // deform vertex array to make wavey water and flags and such
9544                         waveparms[0] = deform->waveparms[0];
9545                         waveparms[1] = deform->waveparms[1];
9546                         waveparms[2] = deform->waveparms[2];
9547                         waveparms[3] = deform->waveparms[3];
9548                         // this is how a divisor of vertex influence on deformation
9549                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9550                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9551                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9552                         {
9553                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9554                                 for (j = 0;j < surface->num_vertices;j++)
9555                                 {
9556                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9557                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9558                                         // if the wavefunc depends on time, evaluate it per-vertex
9559                                         if (waveparms[3])
9560                                         {
9561                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9562                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9563                                         }
9564                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9565                                 }
9566                         }
9567                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9568                         rsurface.vertex3f_bufferobject = 0;
9569                         rsurface.vertex3f_bufferoffset = 0;
9570                         break;
9571                 case Q3DEFORM_BULGE:
9572                         // deform vertex array to make the surface have moving bulges
9573                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9574                         {
9575                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9576                                 for (j = 0;j < surface->num_vertices;j++)
9577                                 {
9578                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9579                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9580                                 }
9581                         }
9582                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9583                         rsurface.vertex3f_bufferobject = 0;
9584                         rsurface.vertex3f_bufferoffset = 0;
9585                         break;
9586                 case Q3DEFORM_MOVE:
9587                         // deform vertex array
9588                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9589                         VectorScale(deform->parms, scale, waveparms);
9590                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9591                         {
9592                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9593                                 for (j = 0;j < surface->num_vertices;j++)
9594                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9595                         }
9596                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9597                         rsurface.vertex3f_bufferobject = 0;
9598                         rsurface.vertex3f_bufferoffset = 0;
9599                         break;
9600                 }
9601         }
9602         // generate texcoords based on the chosen texcoord source
9603         switch(rsurface.texture->tcgen.tcgen)
9604         {
9605         default:
9606         case Q3TCGEN_TEXTURE:
9607                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9608                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9609                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9610                 break;
9611         case Q3TCGEN_LIGHTMAP:
9612                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9613                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9614                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9615                 break;
9616         case Q3TCGEN_VECTOR:
9617                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9618                 {
9619                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9620                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
9621                         {
9622                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9623                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9624                         }
9625                 }
9626                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9627                 rsurface.texcoordtexture2f_bufferobject  = 0;
9628                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9629                 break;
9630         case Q3TCGEN_ENVIRONMENT:
9631                 // make environment reflections using a spheremap
9632                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9633                 {
9634                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9635                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9636                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9637                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9638                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9639                         {
9640                                 // identical to Q3A's method, but executed in worldspace so
9641                                 // carried models can be shiny too
9642
9643                                 float viewer[3], d, reflected[3], worldreflected[3];
9644
9645                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9646                                 // VectorNormalize(viewer);
9647
9648                                 d = DotProduct(normal, viewer);
9649
9650                                 reflected[0] = normal[0]*2*d - viewer[0];
9651                                 reflected[1] = normal[1]*2*d - viewer[1];
9652                                 reflected[2] = normal[2]*2*d - viewer[2];
9653                                 // note: this is proportinal to viewer, so we can normalize later
9654
9655                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9656                                 VectorNormalize(worldreflected);
9657
9658                                 // note: this sphere map only uses world x and z!
9659                                 // so positive and negative y will LOOK THE SAME.
9660                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9661                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9662                         }
9663                 }
9664                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9665                 rsurface.texcoordtexture2f_bufferobject  = 0;
9666                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9667                 break;
9668         }
9669         // the only tcmod that needs software vertex processing is turbulent, so
9670         // check for it here and apply the changes if needed
9671         // and we only support that as the first one
9672         // (handling a mixture of turbulent and other tcmods would be problematic
9673         //  without punting it entirely to a software path)
9674         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9675         {
9676                 amplitude = rsurface.texture->tcmods[0].parms[1];
9677                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9678                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9679                 {
9680                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9681                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
9682                         {
9683                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9684                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9685                         }
9686                 }
9687                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9688                 rsurface.texcoordtexture2f_bufferobject  = 0;
9689                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9690         }
9691         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9692         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9693         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9694         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9695 }
9696
9697 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9698 {
9699         int i, j;
9700         const msurface_t *surface = texturesurfacelist[0];
9701         const msurface_t *surface2;
9702         int firstvertex;
9703         int endvertex;
9704         int numvertices;
9705         int numtriangles;
9706         // TODO: lock all array ranges before render, rather than on each surface
9707         if (texturenumsurfaces == 1)
9708                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9709         else if (r_batchmode.integer == 2)
9710         {
9711                 #define MAXBATCHTRIANGLES 4096
9712                 int batchtriangles = 0;
9713                 static int batchelements[MAXBATCHTRIANGLES*3];
9714                 for (i = 0;i < texturenumsurfaces;i = j)
9715                 {
9716                         surface = texturesurfacelist[i];
9717                         j = i + 1;
9718                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9719                         {
9720                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9721                                 continue;
9722                         }
9723                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9724                         batchtriangles = surface->num_triangles;
9725                         firstvertex = surface->num_firstvertex;
9726                         endvertex = surface->num_firstvertex + surface->num_vertices;
9727                         for (;j < texturenumsurfaces;j++)
9728                         {
9729                                 surface2 = texturesurfacelist[j];
9730                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9731                                         break;
9732                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9733                                 batchtriangles += surface2->num_triangles;
9734                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9735                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9736                         }
9737                         surface2 = texturesurfacelist[j-1];
9738                         numvertices = endvertex - firstvertex;
9739                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9740                 }
9741         }
9742         else if (r_batchmode.integer == 1)
9743         {
9744                 for (i = 0;i < texturenumsurfaces;i = j)
9745                 {
9746                         surface = texturesurfacelist[i];
9747                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9748                                 if (texturesurfacelist[j] != surface2)
9749                                         break;
9750                         surface2 = texturesurfacelist[j-1];
9751                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9752                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9753                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9754                 }
9755         }
9756         else
9757         {
9758                 for (i = 0;i < texturenumsurfaces;i++)
9759                 {
9760                         surface = texturesurfacelist[i];
9761                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9762                 }
9763         }
9764 }
9765
9766 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9767 {
9768         switch(vid.renderpath)
9769         {
9770         case RENDERPATH_CGGL:
9771 #ifdef SUPPORTCG
9772                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9773                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9774 #endif
9775                 break;
9776         case RENDERPATH_GL20:
9777                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9778                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9779                 break;
9780         case RENDERPATH_GL13:
9781         case RENDERPATH_GL11:
9782                 R_Mesh_TexBind(0, surface->lightmaptexture);
9783                 break;
9784         }
9785 }
9786
9787 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9788 {
9789         // pick the closest matching water plane and bind textures
9790         int planeindex, vertexindex;
9791         float d, bestd;
9792         vec3_t vert;
9793         const float *v;
9794         r_waterstate_waterplane_t *p, *bestp;
9795         bestd = 0;
9796         bestp = NULL;
9797         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9798         {
9799                 d = 0;
9800                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9801                 {
9802                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9803                         d += fabs(PlaneDiff(vert, &p->plane));
9804                 }
9805                 if (bestd > d || !bestp)
9806                 {
9807                         bestd = d;
9808                         bestp = p;
9809                 }
9810         }
9811         switch(vid.renderpath)
9812         {
9813         case RENDERPATH_CGGL:
9814 #ifdef SUPPORTCG
9815                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9816                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9817 #endif
9818                 break;
9819         case RENDERPATH_GL20:
9820                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9821                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9822                 break;
9823         case RENDERPATH_GL13:
9824         case RENDERPATH_GL11:
9825                 break;
9826         }
9827 }
9828
9829 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9830 {
9831         int i;
9832         const msurface_t *surface;
9833         if (r_waterstate.renderingscene)
9834                 return;
9835         for (i = 0;i < texturenumsurfaces;i++)
9836         {
9837                 surface = texturesurfacelist[i];
9838                 RSurf_BindLightmapForSurface(surface);
9839                 RSurf_BindReflectionForSurface(surface);
9840                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9841         }
9842 }
9843
9844 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9845 {
9846         int i;
9847         int j;
9848         const msurface_t *surface = texturesurfacelist[0];
9849         const msurface_t *surface2;
9850         int firstvertex;
9851         int endvertex;
9852         int numvertices;
9853         int numtriangles;
9854         if (texturenumsurfaces == 1)
9855         {
9856                 RSurf_BindLightmapForSurface(surface);
9857                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9858         }
9859         else if (r_batchmode.integer == 2)
9860         {
9861 #define MAXBATCHTRIANGLES 4096
9862                 int batchtriangles = 0;
9863                 static int batchelements[MAXBATCHTRIANGLES*3];
9864                 for (i = 0;i < texturenumsurfaces;i = j)
9865                 {
9866                         surface = texturesurfacelist[i];
9867                         RSurf_BindLightmapForSurface(surface);
9868                         j = i + 1;
9869                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9870                         {
9871                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9872                                 continue;
9873                         }
9874                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9875                         batchtriangles = surface->num_triangles;
9876                         firstvertex = surface->num_firstvertex;
9877                         endvertex = surface->num_firstvertex + surface->num_vertices;
9878                         for (;j < texturenumsurfaces;j++)
9879                         {
9880                                 surface2 = texturesurfacelist[j];
9881                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9882                                         break;
9883                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9884                                 batchtriangles += surface2->num_triangles;
9885                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9886                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9887                         }
9888                         surface2 = texturesurfacelist[j-1];
9889                         numvertices = endvertex - firstvertex;
9890                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9891                 }
9892         }
9893         else if (r_batchmode.integer == 1)
9894         {
9895 #if 0
9896                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9897                 for (i = 0;i < texturenumsurfaces;i = j)
9898                 {
9899                         surface = texturesurfacelist[i];
9900                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9901                                 if (texturesurfacelist[j] != surface2)
9902                                         break;
9903                         Con_Printf(" %i", j - i);
9904                 }
9905                 Con_Printf("\n");
9906                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9907 #endif
9908                 for (i = 0;i < texturenumsurfaces;i = j)
9909                 {
9910                         surface = texturesurfacelist[i];
9911                         RSurf_BindLightmapForSurface(surface);
9912                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9913                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9914                                         break;
9915 #if 0
9916                         Con_Printf(" %i", j - i);
9917 #endif
9918                         surface2 = texturesurfacelist[j-1];
9919                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9920                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9921                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9922                 }
9923 #if 0
9924                 Con_Printf("\n");
9925 #endif
9926         }
9927         else
9928         {
9929                 for (i = 0;i < texturenumsurfaces;i++)
9930                 {
9931                         surface = texturesurfacelist[i];
9932                         RSurf_BindLightmapForSurface(surface);
9933                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9934                 }
9935         }
9936 }
9937
9938 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9939 {
9940         int j;
9941         int texturesurfaceindex;
9942         if (r_showsurfaces.integer == 2)
9943         {
9944                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9945                 {
9946                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9947                         for (j = 0;j < surface->num_triangles;j++)
9948                         {
9949                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9950                                 GL_Color(f, f, f, 1);
9951                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9952                         }
9953                 }
9954         }
9955         else
9956         {
9957                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9958                 {
9959                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9960                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9961                         GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
9962                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9963                 }
9964         }
9965 }
9966
9967 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9968 {
9969         int texturesurfaceindex;
9970         int i;
9971         const float *v;
9972         float *c2;
9973         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9974         {
9975                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9976                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
9977                 {
9978                         c2[0] = 0.5;
9979                         c2[1] = 0.5;
9980                         c2[2] = 0.5;
9981                         c2[3] = 1;
9982                 }
9983         }
9984         rsurface.lightmapcolor4f = rsurface.array_color4f;
9985         rsurface.lightmapcolor4f_bufferobject = 0;
9986         rsurface.lightmapcolor4f_bufferoffset = 0;
9987 }
9988
9989 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9990 {
9991         int texturesurfaceindex;
9992         int i;
9993         float f;
9994         const float *v;
9995         const float *c;
9996         float *c2;
9997         if (rsurface.lightmapcolor4f)
9998         {
9999                 // generate color arrays for the surfaces in this list
10000                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10001                 {
10002                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10003                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
10004                         {
10005                                 f = RSurf_FogVertex(v);
10006                                 c2[0] = c[0] * f;
10007                                 c2[1] = c[1] * f;
10008                                 c2[2] = c[2] * f;
10009                                 c2[3] = c[3];
10010                         }
10011                 }
10012         }
10013         else
10014         {
10015                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10016                 {
10017                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10018                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
10019                         {
10020                                 f = RSurf_FogVertex(v);
10021                                 c2[0] = f;
10022                                 c2[1] = f;
10023                                 c2[2] = f;
10024                                 c2[3] = 1;
10025                         }
10026                 }
10027         }
10028         rsurface.lightmapcolor4f = rsurface.array_color4f;
10029         rsurface.lightmapcolor4f_bufferobject = 0;
10030         rsurface.lightmapcolor4f_bufferoffset = 0;
10031 }
10032
10033 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10034 {
10035         int texturesurfaceindex;
10036         int i;
10037         float f;
10038         const float *v;
10039         const float *c;
10040         float *c2;
10041         if (!rsurface.lightmapcolor4f)
10042                 return;
10043         // generate color arrays for the surfaces in this list
10044         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10045         {
10046                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10047                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
10048                 {
10049                         f = RSurf_FogVertex(v);
10050                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10051                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10052                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10053                         c2[3] = c[3];
10054                 }
10055         }
10056         rsurface.lightmapcolor4f = rsurface.array_color4f;
10057         rsurface.lightmapcolor4f_bufferobject = 0;
10058         rsurface.lightmapcolor4f_bufferoffset = 0;
10059 }
10060
10061 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10062 {
10063         int texturesurfaceindex;
10064         int i;
10065         const float *c;
10066         float *c2;
10067         if (!rsurface.lightmapcolor4f)
10068                 return;
10069         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10070         {
10071                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10072                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
10073                 {
10074                         c2[0] = c[0] * r;
10075                         c2[1] = c[1] * g;
10076                         c2[2] = c[2] * b;
10077                         c2[3] = c[3] * a;
10078                 }
10079         }
10080         rsurface.lightmapcolor4f = rsurface.array_color4f;
10081         rsurface.lightmapcolor4f_bufferobject = 0;
10082         rsurface.lightmapcolor4f_bufferoffset = 0;
10083 }
10084
10085 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10086 {
10087         int texturesurfaceindex;
10088         int i;
10089         const float *c;
10090         float *c2;
10091         if (!rsurface.lightmapcolor4f)
10092                 return;
10093         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10094         {
10095                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10096                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
10097                 {
10098                         c2[0] = c[0] + r_refdef.scene.ambient;
10099                         c2[1] = c[1] + r_refdef.scene.ambient;
10100                         c2[2] = c[2] + r_refdef.scene.ambient;
10101                         c2[3] = c[3];
10102                 }
10103         }
10104         rsurface.lightmapcolor4f = rsurface.array_color4f;
10105         rsurface.lightmapcolor4f_bufferobject = 0;
10106         rsurface.lightmapcolor4f_bufferoffset = 0;
10107 }
10108
10109 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10110 {
10111         // TODO: optimize
10112         rsurface.lightmapcolor4f = NULL;
10113         rsurface.lightmapcolor4f_bufferobject = 0;
10114         rsurface.lightmapcolor4f_bufferoffset = 0;
10115         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10116         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10117         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10118         GL_Color(r, g, b, a);
10119         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10120 }
10121
10122 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10123 {
10124         // TODO: optimize applyfog && applycolor case
10125         // just apply fog if necessary, and tint the fog color array if necessary
10126         rsurface.lightmapcolor4f = NULL;
10127         rsurface.lightmapcolor4f_bufferobject = 0;
10128         rsurface.lightmapcolor4f_bufferoffset = 0;
10129         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10130         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10131         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10132         GL_Color(r, g, b, a);
10133         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10134 }
10135
10136 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10137 {
10138         int texturesurfaceindex;
10139         int i;
10140         float *c;
10141         // TODO: optimize
10142         if (texturesurfacelist[0]->lightmapinfo)
10143         {
10144                 // generate color arrays for the surfaces in this list
10145                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10146                 {
10147                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10148                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10149                         {
10150                                 if (surface->lightmapinfo->samples)
10151                                 {
10152                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10153                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10154                                         VectorScale(lm, scale, c);
10155                                         if (surface->lightmapinfo->styles[1] != 255)
10156                                         {
10157                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10158                                                 lm += size3;
10159                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10160                                                 VectorMA(c, scale, lm, c);
10161                                                 if (surface->lightmapinfo->styles[2] != 255)
10162                                                 {
10163                                                         lm += size3;
10164                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10165                                                         VectorMA(c, scale, lm, c);
10166                                                         if (surface->lightmapinfo->styles[3] != 255)
10167                                                         {
10168                                                                 lm += size3;
10169                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10170                                                                 VectorMA(c, scale, lm, c);
10171                                                         }
10172                                                 }
10173                                         }
10174                                 }
10175                                 else
10176                                         VectorClear(c);
10177                                 c[3] = 1;
10178                         }
10179                 }
10180                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10181                 rsurface.lightmapcolor4f_bufferobject = 0;
10182                 rsurface.lightmapcolor4f_bufferoffset = 0;
10183         }
10184         else
10185         {
10186                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10187                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10188                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10189         }
10190         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10191         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10192         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10193         GL_Color(r, g, b, a);
10194         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10195 }
10196
10197 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10198 {
10199         int texturesurfaceindex;
10200         int i;
10201         float f;
10202         float alpha;
10203         const float *v;
10204         const float *n;
10205         float *c;
10206         vec3_t ambientcolor;
10207         vec3_t diffusecolor;
10208         vec3_t lightdir;
10209         // TODO: optimize
10210         // model lighting
10211         VectorCopy(rsurface.modellight_lightdir, lightdir);
10212         f = 0.5f * r_refdef.lightmapintensity;
10213         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10214         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10215         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10216         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10217         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10218         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10219         alpha = *a;
10220         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10221         {
10222                 // generate color arrays for the surfaces in this list
10223                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10224                 {
10225                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10226                         int numverts = surface->num_vertices;
10227                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10228                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10229                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10230                         // q3-style directional shading
10231                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10232                         {
10233                                 if ((f = DotProduct(n, lightdir)) > 0)
10234                                         VectorMA(ambientcolor, f, diffusecolor, c);
10235                                 else
10236                                         VectorCopy(ambientcolor, c);
10237                                 c[3] = alpha;
10238                         }
10239                 }
10240                 *r = 1;
10241                 *g = 1;
10242                 *b = 1;
10243                 *a = 1;
10244                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10245                 rsurface.lightmapcolor4f_bufferobject = 0;
10246                 rsurface.lightmapcolor4f_bufferoffset = 0;
10247                 *applycolor = false;
10248         }
10249         else
10250         {
10251                 *r = ambientcolor[0];
10252                 *g = ambientcolor[1];
10253                 *b = ambientcolor[2];
10254                 rsurface.lightmapcolor4f = NULL;
10255                 rsurface.lightmapcolor4f_bufferobject = 0;
10256                 rsurface.lightmapcolor4f_bufferoffset = 0;
10257         }
10258 }
10259
10260 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10261 {
10262         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10263         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10264         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10265         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10266         GL_Color(r, g, b, a);
10267         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10268 }
10269
10270 void RSurf_SetupDepthAndCulling(void)
10271 {
10272         // submodels are biased to avoid z-fighting with world surfaces that they
10273         // may be exactly overlapping (avoids z-fighting artifacts on certain
10274         // doors and things in Quake maps)
10275         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10276         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10277         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10278         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10279 }
10280
10281 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10282 {
10283         // transparent sky would be ridiculous
10284         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10285                 return;
10286         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10287         skyrenderlater = true;
10288         RSurf_SetupDepthAndCulling();
10289         GL_DepthMask(true);
10290         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10291         // skymasking on them, and Quake3 never did sky masking (unlike
10292         // software Quake and software Quake2), so disable the sky masking
10293         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10294         // and skymasking also looks very bad when noclipping outside the
10295         // level, so don't use it then either.
10296         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10297         {
10298                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10299                 R_Mesh_ColorPointer(NULL, 0, 0);
10300                 R_Mesh_ResetTextureState();
10301                 if (skyrendermasked)
10302                 {
10303                         R_SetupShader_DepthOrShadow();
10304                         // depth-only (masking)
10305                         GL_ColorMask(0,0,0,0);
10306                         // just to make sure that braindead drivers don't draw
10307                         // anything despite that colormask...
10308                         GL_BlendFunc(GL_ZERO, GL_ONE);
10309                 }
10310                 else
10311                 {
10312                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10313                         // fog sky
10314                         GL_BlendFunc(GL_ONE, GL_ZERO);
10315                 }
10316                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10317                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10318                 if (skyrendermasked)
10319                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10320         }
10321         R_Mesh_ResetTextureState();
10322         GL_Color(1, 1, 1, 1);
10323 }
10324
10325 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10326 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10327 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10328 {
10329         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10330                 return;
10331         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10332         if (prepass)
10333         {
10334                 // render screenspace normalmap to texture
10335                 GL_DepthMask(true);
10336                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10337                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10338         }
10339         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10340         {
10341                 // render water or distortion background, then blend surface on top
10342                 GL_DepthMask(true);
10343                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10344                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10345                 GL_DepthMask(false);
10346                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10347                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10348                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10349                 else
10350                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10351         }
10352         else
10353         {
10354                 // render surface normally
10355                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10356                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10358                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10359                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10360                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10361                 else
10362                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10363         }
10364 }
10365
10366 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10367 {
10368         // OpenGL 1.3 path - anything not completely ancient
10369         int texturesurfaceindex;
10370         qboolean applycolor;
10371         qboolean applyfog;
10372         int layerindex;
10373         const texturelayer_t *layer;
10374         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10375
10376         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10377         {
10378                 vec4_t layercolor;
10379                 int layertexrgbscale;
10380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10381                 {
10382                         if (layerindex == 0)
10383                                 GL_AlphaTest(true);
10384                         else
10385                         {
10386                                 GL_AlphaTest(false);
10387                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10388                         }
10389                 }
10390                 GL_DepthMask(layer->depthmask && writedepth);
10391                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10392                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10393                 {
10394                         layertexrgbscale = 4;
10395                         VectorScale(layer->color, 0.25f, layercolor);
10396                 }
10397                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10398                 {
10399                         layertexrgbscale = 2;
10400                         VectorScale(layer->color, 0.5f, layercolor);
10401                 }
10402                 else
10403                 {
10404                         layertexrgbscale = 1;
10405                         VectorScale(layer->color, 1.0f, layercolor);
10406                 }
10407                 layercolor[3] = layer->color[3];
10408                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10409                 R_Mesh_ColorPointer(NULL, 0, 0);
10410                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10411                 switch (layer->type)
10412                 {
10413                 case TEXTURELAYERTYPE_LITTEXTURE:
10414                         // single-pass lightmapped texture with 2x rgbscale
10415                         R_Mesh_TexBind(0, r_texture_white);
10416                         R_Mesh_TexMatrix(0, NULL);
10417                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10418                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10419                         R_Mesh_TexBind(1, layer->texture);
10420                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10421                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10422                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10423                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10424                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10425                         else if (rsurface.uselightmaptexture)
10426                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10427                         else
10428                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10429                         break;
10430                 case TEXTURELAYERTYPE_TEXTURE:
10431                         // singletexture unlit texture with transparency support
10432                         R_Mesh_TexBind(0, layer->texture);
10433                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10434                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10435                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10436                         R_Mesh_TexBind(1, 0);
10437                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10438                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10439                         break;
10440                 case TEXTURELAYERTYPE_FOG:
10441                         // singletexture fogging
10442                         if (layer->texture)
10443                         {
10444                                 R_Mesh_TexBind(0, layer->texture);
10445                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10446                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10447                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10448                         }
10449                         else
10450                         {
10451                                 R_Mesh_TexBind(0, 0);
10452                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10453                         }
10454                         R_Mesh_TexBind(1, 0);
10455                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10456                         // generate a color array for the fog pass
10457                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10458                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10459                         {
10460                                 int i;
10461                                 float f;
10462                                 const float *v;
10463                                 float *c;
10464                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10465                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10466                                 {
10467                                         f = 1 - RSurf_FogVertex(v);
10468                                         c[0] = layercolor[0];
10469                                         c[1] = layercolor[1];
10470                                         c[2] = layercolor[2];
10471                                         c[3] = f * layercolor[3];
10472                                 }
10473                         }
10474                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10475                         break;
10476                 default:
10477                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10478                 }
10479         }
10480         CHECKGLERROR
10481         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10482         {
10483                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10484                 GL_AlphaTest(false);
10485         }
10486 }
10487
10488 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10489 {
10490         // OpenGL 1.1 - crusty old voodoo path
10491         int texturesurfaceindex;
10492         qboolean applyfog;
10493         int layerindex;
10494         const texturelayer_t *layer;
10495         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10496
10497         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10498         {
10499                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10500                 {
10501                         if (layerindex == 0)
10502                                 GL_AlphaTest(true);
10503                         else
10504                         {
10505                                 GL_AlphaTest(false);
10506                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10507                         }
10508                 }
10509                 GL_DepthMask(layer->depthmask && writedepth);
10510                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10511                 R_Mesh_ColorPointer(NULL, 0, 0);
10512                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10513                 switch (layer->type)
10514                 {
10515                 case TEXTURELAYERTYPE_LITTEXTURE:
10516                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10517                         {
10518                                 // two-pass lit texture with 2x rgbscale
10519                                 // first the lightmap pass
10520                                 R_Mesh_TexBind(0, r_texture_white);
10521                                 R_Mesh_TexMatrix(0, NULL);
10522                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10523                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10524                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10525                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10526                                 else if (rsurface.uselightmaptexture)
10527                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10528                                 else
10529                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10530                                 // then apply the texture to it
10531                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10532                                 R_Mesh_TexBind(0, layer->texture);
10533                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10534                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10535                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10536                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, 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);
10537                         }
10538                         else
10539                         {
10540                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10541                                 R_Mesh_TexBind(0, layer->texture);
10542                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10543                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10544                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10545                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10546                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 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);
10547                                 else
10548                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 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);
10549                         }
10550                         break;
10551                 case TEXTURELAYERTYPE_TEXTURE:
10552                         // singletexture unlit texture with transparency support
10553                         R_Mesh_TexBind(0, layer->texture);
10554                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10555                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10556                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10557                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, 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);
10558                         break;
10559                 case TEXTURELAYERTYPE_FOG:
10560                         // singletexture fogging
10561                         if (layer->texture)
10562                         {
10563                                 R_Mesh_TexBind(0, layer->texture);
10564                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10565                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10566                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10567                         }
10568                         else
10569                         {
10570                                 R_Mesh_TexBind(0, 0);
10571                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10572                         }
10573                         // generate a color array for the fog pass
10574                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10575                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10576                         {
10577                                 int i;
10578                                 float f;
10579                                 const float *v;
10580                                 float *c;
10581                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10582                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10583                                 {
10584                                         f = 1 - RSurf_FogVertex(v);
10585                                         c[0] = layer->color[0];
10586                                         c[1] = layer->color[1];
10587                                         c[2] = layer->color[2];
10588                                         c[3] = f * layer->color[3];
10589                                 }
10590                         }
10591                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10592                         break;
10593                 default:
10594                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10595                 }
10596         }
10597         CHECKGLERROR
10598         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10599         {
10600                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10601                 GL_AlphaTest(false);
10602         }
10603 }
10604
10605 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10606 {
10607         float c[4];
10608
10609         GL_AlphaTest(false);
10610         R_Mesh_ColorPointer(NULL, 0, 0);
10611         R_Mesh_ResetTextureState();
10612         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10613
10614         if(rsurface.texture && rsurface.texture->currentskinframe)
10615         {
10616                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10617                 c[3] *= rsurface.texture->currentalpha;
10618         }
10619         else
10620         {
10621                 c[0] = 1;
10622                 c[1] = 0;
10623                 c[2] = 1;
10624                 c[3] = 1;
10625         }
10626
10627         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10628         {
10629                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10630                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10631                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10632         }
10633
10634         // brighten it up (as texture value 127 means "unlit")
10635         c[0] *= 2 * r_refdef.view.colorscale;
10636         c[1] *= 2 * r_refdef.view.colorscale;
10637         c[2] *= 2 * r_refdef.view.colorscale;
10638
10639         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10640                 c[3] *= r_wateralpha.value;
10641
10642         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10643         {
10644                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10645                 GL_DepthMask(false);
10646         }
10647         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10648         {
10649                 GL_BlendFunc(GL_ONE, GL_ONE);
10650                 GL_DepthMask(false);
10651         }
10652         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10653         {
10654                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10655                 GL_DepthMask(false);
10656         }
10657         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10658         {
10659                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10660                 GL_DepthMask(false);
10661         }
10662         else
10663         {
10664                 GL_BlendFunc(GL_ONE, GL_ZERO);
10665                 GL_DepthMask(writedepth);
10666         }
10667
10668         rsurface.lightmapcolor4f = NULL;
10669
10670         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10671         {
10672                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10673
10674                 rsurface.lightmapcolor4f = NULL;
10675                 rsurface.lightmapcolor4f_bufferobject = 0;
10676                 rsurface.lightmapcolor4f_bufferoffset = 0;
10677         }
10678         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10679         {
10680                 qboolean applycolor = true;
10681                 float one = 1.0;
10682
10683                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10684
10685                 r_refdef.lightmapintensity = 1;
10686                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10687                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10688         }
10689         else
10690         {
10691                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10692
10693                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10694                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10695                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10696         }
10697
10698         if(!rsurface.lightmapcolor4f)
10699                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10700
10701         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10702         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10703         if(r_refdef.fogenabled)
10704                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10705
10706         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10707         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10708 }
10709
10710 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10711 {
10712         CHECKGLERROR
10713         RSurf_SetupDepthAndCulling();
10714         if (r_showsurfaces.integer == 3 && !prepass)
10715         {
10716                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10717                 return;
10718         }
10719         switch (vid.renderpath)
10720         {
10721         case RENDERPATH_GL20:
10722         case RENDERPATH_CGGL:
10723                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10724                 break;
10725         case RENDERPATH_GL13:
10726                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10727                 break;
10728         case RENDERPATH_GL11:
10729                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10730                 break;
10731         }
10732         CHECKGLERROR
10733 }
10734
10735 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10736 {
10737         CHECKGLERROR
10738         RSurf_SetupDepthAndCulling();
10739         if (r_showsurfaces.integer == 3 && !prepass)
10740         {
10741                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10742                 return;
10743         }
10744         switch (vid.renderpath)
10745         {
10746         case RENDERPATH_GL20:
10747         case RENDERPATH_CGGL:
10748                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10749                 break;
10750         case RENDERPATH_GL13:
10751                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10752                 break;
10753         case RENDERPATH_GL11:
10754                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10755                 break;
10756         }
10757         CHECKGLERROR
10758 }
10759
10760 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10761 {
10762         int i, j;
10763         int texturenumsurfaces, endsurface;
10764         texture_t *texture;
10765         const msurface_t *surface;
10766         const msurface_t *texturesurfacelist[256];
10767
10768         // if the model is static it doesn't matter what value we give for
10769         // wantnormals and wanttangents, so this logic uses only rules applicable
10770         // to a model, knowing that they are meaningless otherwise
10771         if (ent == r_refdef.scene.worldentity)
10772                 RSurf_ActiveWorldEntity();
10773         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10774                 RSurf_ActiveModelEntity(ent, false, false, false);
10775         else
10776         {
10777                 switch (vid.renderpath)
10778                 {
10779                 case RENDERPATH_GL20:
10780                 case RENDERPATH_CGGL:
10781                         RSurf_ActiveModelEntity(ent, true, true, false);
10782                         break;
10783                 case RENDERPATH_GL13:
10784                 case RENDERPATH_GL11:
10785                         RSurf_ActiveModelEntity(ent, true, false, false);
10786                         break;
10787                 }
10788         }
10789
10790         if (r_transparentdepthmasking.integer)
10791         {
10792                 qboolean setup = false;
10793                 for (i = 0;i < numsurfaces;i = j)
10794                 {
10795                         j = i + 1;
10796                         surface = rsurface.modelsurfaces + surfacelist[i];
10797                         texture = surface->texture;
10798                         rsurface.texture = R_GetCurrentTexture(texture);
10799                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10800                         // scan ahead until we find a different texture
10801                         endsurface = min(i + 1024, numsurfaces);
10802                         texturenumsurfaces = 0;
10803                         texturesurfacelist[texturenumsurfaces++] = surface;
10804                         for (;j < endsurface;j++)
10805                         {
10806                                 surface = rsurface.modelsurfaces + surfacelist[j];
10807                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10808                                         break;
10809                                 texturesurfacelist[texturenumsurfaces++] = surface;
10810                         }
10811                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10812                                 continue;
10813                         // render the range of surfaces as depth
10814                         if (!setup)
10815                         {
10816                                 setup = true;
10817                                 GL_ColorMask(0,0,0,0);
10818                                 GL_Color(1,1,1,1);
10819                                 GL_DepthTest(true);
10820                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10821                                 GL_DepthMask(true);
10822                                 GL_AlphaTest(false);
10823                                 R_Mesh_ColorPointer(NULL, 0, 0);
10824                                 R_Mesh_ResetTextureState();
10825                                 R_SetupShader_DepthOrShadow();
10826                         }
10827                         RSurf_SetupDepthAndCulling();
10828                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10829                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10830                 }
10831                 if (setup)
10832                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10833         }
10834
10835         for (i = 0;i < numsurfaces;i = j)
10836         {
10837                 j = i + 1;
10838                 surface = rsurface.modelsurfaces + surfacelist[i];
10839                 texture = surface->texture;
10840                 rsurface.texture = R_GetCurrentTexture(texture);
10841                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10842                 // scan ahead until we find a different texture
10843                 endsurface = min(i + 1024, numsurfaces);
10844                 texturenumsurfaces = 0;
10845                 texturesurfacelist[texturenumsurfaces++] = surface;
10846                 for (;j < endsurface;j++)
10847                 {
10848                         surface = rsurface.modelsurfaces + surfacelist[j];
10849                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10850                                 break;
10851                         texturesurfacelist[texturenumsurfaces++] = surface;
10852                 }
10853                 // render the range of surfaces
10854                 if (ent == r_refdef.scene.worldentity)
10855                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10856                 else
10857                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10858         }
10859         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10860         GL_AlphaTest(false);
10861 }
10862
10863 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10864 {
10865         // transparent surfaces get pushed off into the transparent queue
10866         int surfacelistindex;
10867         const msurface_t *surface;
10868         vec3_t tempcenter, center;
10869         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10870         {
10871                 surface = texturesurfacelist[surfacelistindex];
10872                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10873                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10874                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10875                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10876                 if (queueentity->transparent_offset) // transparent offset
10877                 {
10878                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10879                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10880                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10881                 }
10882                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10883         }
10884 }
10885
10886 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10887 {
10888         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10889         CHECKGLERROR
10890         if (depthonly)
10891         {
10892                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10893                         return;
10894                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10895                         return;
10896                 RSurf_SetupDepthAndCulling();
10897                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10898                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10899         }
10900         else if (prepass)
10901         {
10902                 if (!rsurface.texture->currentnumlayers)
10903                         return;
10904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10905                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10906                 else
10907                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10908         }
10909         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10910         {
10911                 RSurf_SetupDepthAndCulling();
10912                 GL_AlphaTest(false);
10913                 R_Mesh_ColorPointer(NULL, 0, 0);
10914                 R_Mesh_ResetTextureState();
10915                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10916                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10917                 GL_DepthMask(true);
10918                 GL_BlendFunc(GL_ONE, GL_ZERO);
10919                 GL_Color(0, 0, 0, 1);
10920                 GL_DepthTest(writedepth);
10921                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10922         }
10923         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10924         {
10925                 RSurf_SetupDepthAndCulling();
10926                 GL_AlphaTest(false);
10927                 R_Mesh_ColorPointer(NULL, 0, 0);
10928                 R_Mesh_ResetTextureState();
10929                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10930                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10931                 GL_DepthMask(true);
10932                 GL_BlendFunc(GL_ONE, GL_ZERO);
10933                 GL_DepthTest(true);
10934                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10935         }
10936         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10937                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10938         else if (!rsurface.texture->currentnumlayers)
10939                 return;
10940         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10941         {
10942                 // in the deferred case, transparent surfaces were queued during prepass
10943                 if (!r_shadow_usingdeferredprepass)
10944                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10945         }
10946         else
10947         {
10948                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10949                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10950         }
10951         CHECKGLERROR
10952 }
10953
10954 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10955 {
10956         int i, j;
10957         texture_t *texture;
10958         // break the surface list down into batches by texture and use of lightmapping
10959         for (i = 0;i < numsurfaces;i = j)
10960         {
10961                 j = i + 1;
10962                 // texture is the base texture pointer, rsurface.texture is the
10963                 // current frame/skin the texture is directing us to use (for example
10964                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10965                 // use skin 1 instead)
10966                 texture = surfacelist[i]->texture;
10967                 rsurface.texture = R_GetCurrentTexture(texture);
10968                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10969                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10970                 {
10971                         // if this texture is not the kind we want, skip ahead to the next one
10972                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10973                                 ;
10974                         continue;
10975                 }
10976                 // simply scan ahead until we find a different texture or lightmap state
10977                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10978                         ;
10979                 // render the range of surfaces
10980                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10981         }
10982 }
10983
10984 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10985 {
10986         CHECKGLERROR
10987         if (depthonly)
10988         {
10989                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10990                         return;
10991                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10992                         return;
10993                 RSurf_SetupDepthAndCulling();
10994                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10995                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10996         }
10997         else if (prepass)
10998         {
10999                 if (!rsurface.texture->currentnumlayers)
11000                         return;
11001                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11002                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11003                 else
11004                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11005         }
11006         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11007         {
11008                 RSurf_SetupDepthAndCulling();
11009                 GL_AlphaTest(false);
11010                 R_Mesh_ColorPointer(NULL, 0, 0);
11011                 R_Mesh_ResetTextureState();
11012                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11013                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11014                 GL_DepthMask(true);
11015                 GL_BlendFunc(GL_ONE, GL_ZERO);
11016                 GL_Color(0, 0, 0, 1);
11017                 GL_DepthTest(writedepth);
11018                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11019         }
11020         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11021         {
11022                 RSurf_SetupDepthAndCulling();
11023                 GL_AlphaTest(false);
11024                 R_Mesh_ColorPointer(NULL, 0, 0);
11025                 R_Mesh_ResetTextureState();
11026                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11027                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11028                 GL_DepthMask(true);
11029                 GL_BlendFunc(GL_ONE, GL_ZERO);
11030                 GL_DepthTest(true);
11031                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11032         }
11033         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11034                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11035         else if (!rsurface.texture->currentnumlayers)
11036                 return;
11037         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11038         {
11039                 // in the deferred case, transparent surfaces were queued during prepass
11040                 if (!r_shadow_usingdeferredprepass)
11041                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11042         }
11043         else
11044         {
11045                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11046                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11047         }
11048         CHECKGLERROR
11049 }
11050
11051 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11052 {
11053         int i, j;
11054         texture_t *texture;
11055         // break the surface list down into batches by texture and use of lightmapping
11056         for (i = 0;i < numsurfaces;i = j)
11057         {
11058                 j = i + 1;
11059                 // texture is the base texture pointer, rsurface.texture is the
11060                 // current frame/skin the texture is directing us to use (for example
11061                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11062                 // use skin 1 instead)
11063                 texture = surfacelist[i]->texture;
11064                 rsurface.texture = R_GetCurrentTexture(texture);
11065                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11066                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11067                 {
11068                         // if this texture is not the kind we want, skip ahead to the next one
11069                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11070                                 ;
11071                         continue;
11072                 }
11073                 // simply scan ahead until we find a different texture or lightmap state
11074                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11075                         ;
11076                 // render the range of surfaces
11077                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11078         }
11079 }
11080
11081 float locboxvertex3f[6*4*3] =
11082 {
11083         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11084         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11085         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11086         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11087         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11088         1,0,0, 0,0,0, 0,1,0, 1,1,0
11089 };
11090
11091 unsigned short locboxelements[6*2*3] =
11092 {
11093          0, 1, 2, 0, 2, 3,
11094          4, 5, 6, 4, 6, 7,
11095          8, 9,10, 8,10,11,
11096         12,13,14, 12,14,15,
11097         16,17,18, 16,18,19,
11098         20,21,22, 20,22,23
11099 };
11100
11101 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11102 {
11103         int i, j;
11104         cl_locnode_t *loc = (cl_locnode_t *)ent;
11105         vec3_t mins, size;
11106         float vertex3f[6*4*3];
11107         CHECKGLERROR
11108         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11109         GL_DepthMask(false);
11110         GL_DepthRange(0, 1);
11111         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11112         GL_DepthTest(true);
11113         GL_CullFace(GL_NONE);
11114         R_EntityMatrix(&identitymatrix);
11115
11116         R_Mesh_VertexPointer(vertex3f, 0, 0);
11117         R_Mesh_ColorPointer(NULL, 0, 0);
11118         R_Mesh_ResetTextureState();
11119         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11120
11121         i = surfacelist[0];
11122         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11123                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11124                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11125                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11126
11127         if (VectorCompare(loc->mins, loc->maxs))
11128         {
11129                 VectorSet(size, 2, 2, 2);
11130                 VectorMA(loc->mins, -0.5f, size, mins);
11131         }
11132         else
11133         {
11134                 VectorCopy(loc->mins, mins);
11135                 VectorSubtract(loc->maxs, loc->mins, size);
11136         }
11137
11138         for (i = 0;i < 6*4*3;)
11139                 for (j = 0;j < 3;j++, i++)
11140                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11141
11142         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11143 }
11144
11145 void R_DrawLocs(void)
11146 {
11147         int index;
11148         cl_locnode_t *loc, *nearestloc;
11149         vec3_t center;
11150         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11151         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11152         {
11153                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11154                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11155         }
11156 }
11157
11158 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11159 {
11160         if (decalsystem->decals)
11161                 Mem_Free(decalsystem->decals);
11162         memset(decalsystem, 0, sizeof(*decalsystem));
11163 }
11164
11165 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)
11166 {
11167         tridecal_t *decal;
11168         tridecal_t *decals;
11169         int i;
11170         int maxdecals;
11171
11172         // expand or initialize the system
11173         if (decalsystem->maxdecals <= decalsystem->numdecals)
11174         {
11175                 decalsystem_t old = *decalsystem;
11176                 qboolean useshortelements;
11177                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11178                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11179                 decalsystem->decals = 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)));
11180                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11181                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11182                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11183                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11184                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11185                 if (decalsystem->numdecals)
11186                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11187                 if (old.decals)
11188                         Mem_Free(old.decals);
11189                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11190                         decalsystem->element3i[i] = i;
11191                 if (useshortelements)
11192                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11193                                 decalsystem->element3s[i] = i;
11194         }
11195
11196         // grab a decal and search for another free slot for the next one
11197         maxdecals = decalsystem->maxdecals;
11198         decals = decalsystem->decals;
11199         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11200         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11201                 ;
11202         decalsystem->freedecal = i;
11203         if (decalsystem->numdecals <= i)
11204                 decalsystem->numdecals = i + 1;
11205
11206         // initialize the decal
11207         decal->lived = 0;
11208         decal->triangleindex = triangleindex;
11209         decal->surfaceindex = surfaceindex;
11210         decal->decalsequence = decalsequence;
11211         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11212         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11213         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11214         decal->color4ub[0][3] = 255;
11215         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11216         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11217         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11218         decal->color4ub[1][3] = 255;
11219         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11220         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11221         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11222         decal->color4ub[2][3] = 255;
11223         decal->vertex3f[0][0] = v0[0];
11224         decal->vertex3f[0][1] = v0[1];
11225         decal->vertex3f[0][2] = v0[2];
11226         decal->vertex3f[1][0] = v1[0];
11227         decal->vertex3f[1][1] = v1[1];
11228         decal->vertex3f[1][2] = v1[2];
11229         decal->vertex3f[2][0] = v2[0];
11230         decal->vertex3f[2][1] = v2[1];
11231         decal->vertex3f[2][2] = v2[2];
11232         decal->texcoord2f[0][0] = t0[0];
11233         decal->texcoord2f[0][1] = t0[1];
11234         decal->texcoord2f[1][0] = t1[0];
11235         decal->texcoord2f[1][1] = t1[1];
11236         decal->texcoord2f[2][0] = t2[0];
11237         decal->texcoord2f[2][1] = t2[1];
11238 }
11239
11240 extern cvar_t cl_decals_bias;
11241 extern cvar_t cl_decals_models;
11242 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11243 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)
11244 {
11245         matrix4x4_t projection;
11246         decalsystem_t *decalsystem;
11247         qboolean dynamic;
11248         dp_model_t *model;
11249         const float *vertex3f;
11250         const msurface_t *surface;
11251         const msurface_t *surfaces;
11252         const int *surfacelist;
11253         const texture_t *texture;
11254         int numvertices;
11255         int numtriangles;
11256         int numsurfacelist;
11257         int surfacelistindex;
11258         int surfaceindex;
11259         int triangleindex;
11260         int decalsurfaceindex;
11261         int cornerindex;
11262         int index;
11263         int numpoints;
11264         const int *e;
11265         float localorigin[3];
11266         float localnormal[3];
11267         float localmins[3];
11268         float localmaxs[3];
11269         float localsize;
11270         float ilocalsize;
11271         float v[9][3];
11272         float tc[9][2];
11273         float c[9][4];
11274         //float normal[3];
11275         float planes[6][4];
11276         float f;
11277         float points[2][9][3];
11278         float angles[3];
11279         float temp[3];
11280
11281         decalsystem = &ent->decalsystem;
11282         model = ent->model;
11283         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11284         {
11285                 R_DecalSystem_Reset(&ent->decalsystem);
11286                 return;
11287         }
11288
11289         if (!model->brush.data_nodes && !cl_decals_models.integer)
11290         {
11291                 if (decalsystem->model)
11292                         R_DecalSystem_Reset(decalsystem);
11293                 return;
11294         }
11295
11296         if (decalsystem->model != model)
11297                 R_DecalSystem_Reset(decalsystem);
11298         decalsystem->model = model;
11299
11300         RSurf_ActiveModelEntity(ent, false, false, false);
11301
11302         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11303         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11304         VectorNormalize(localnormal);
11305         localsize = worldsize*rsurface.inversematrixscale;
11306         ilocalsize = 1.0f / localsize;
11307         localmins[0] = localorigin[0] - localsize;
11308         localmins[1] = localorigin[1] - localsize;
11309         localmins[2] = localorigin[2] - localsize;
11310         localmaxs[0] = localorigin[0] + localsize;
11311         localmaxs[1] = localorigin[1] + localsize;
11312         localmaxs[2] = localorigin[2] + localsize;
11313
11314         //VectorCopy(localnormal, planes[4]);
11315         //VectorVectors(planes[4], planes[2], planes[0]);
11316         AnglesFromVectors(angles, localnormal, NULL, false);
11317         AngleVectors(angles, planes[0], planes[2], planes[4]);
11318         VectorNegate(planes[0], planes[1]);
11319         VectorNegate(planes[2], planes[3]);
11320         VectorNegate(planes[4], planes[5]);
11321         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11322         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11323         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11324         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11325         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11326         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11327
11328 #if 1
11329 // works
11330 {
11331         matrix4x4_t forwardprojection;
11332         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11333         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11334 }
11335 #else
11336 // broken
11337 {
11338         float projectionvector[4][3];
11339         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11340         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11341         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11342         projectionvector[0][0] = planes[0][0] * ilocalsize;
11343         projectionvector[0][1] = planes[1][0] * ilocalsize;
11344         projectionvector[0][2] = planes[2][0] * ilocalsize;
11345         projectionvector[1][0] = planes[0][1] * ilocalsize;
11346         projectionvector[1][1] = planes[1][1] * ilocalsize;
11347         projectionvector[1][2] = planes[2][1] * ilocalsize;
11348         projectionvector[2][0] = planes[0][2] * ilocalsize;
11349         projectionvector[2][1] = planes[1][2] * ilocalsize;
11350         projectionvector[2][2] = planes[2][2] * ilocalsize;
11351         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11352         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11353         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11354         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11355 }
11356 #endif
11357
11358         dynamic = model->surfmesh.isanimated;
11359         vertex3f = rsurface.modelvertex3f;
11360         numsurfacelist = model->nummodelsurfaces;
11361         surfacelist = model->sortedmodelsurfaces;
11362         surfaces = model->data_surfaces;
11363         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11364         {
11365                 surfaceindex = surfacelist[surfacelistindex];
11366                 surface = surfaces + surfaceindex;
11367                 // skip transparent surfaces
11368                 texture = surface->texture;
11369                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11370                         continue;
11371                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11372                         continue;
11373                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11374                         continue;
11375                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11376                 numvertices = surface->num_vertices;
11377                 numtriangles = surface->num_triangles;
11378                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11379                 {
11380                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11381                         {
11382                                 index = 3*e[cornerindex];
11383                                 VectorCopy(vertex3f + index, v[cornerindex]);
11384                         }
11385                         // cull backfaces
11386                         //TriangleNormal(v[0], v[1], v[2], normal);
11387                         //if (DotProduct(normal, localnormal) < 0.0f)
11388                         //      continue;
11389                         // clip by each of the box planes formed from the projection matrix
11390                         // if anything survives, we emit the decal
11391                         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]);
11392                         if (numpoints < 3)
11393                                 continue;
11394                         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]);
11395                         if (numpoints < 3)
11396                                 continue;
11397                         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]);
11398                         if (numpoints < 3)
11399                                 continue;
11400                         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]);
11401                         if (numpoints < 3)
11402                                 continue;
11403                         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]);
11404                         if (numpoints < 3)
11405                                 continue;
11406                         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]);
11407                         if (numpoints < 3)
11408                                 continue;
11409                         // some part of the triangle survived, so we have to accept it...
11410                         if (dynamic)
11411                         {
11412                                 // dynamic always uses the original triangle
11413                                 numpoints = 3;
11414                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11415                                 {
11416                                         index = 3*e[cornerindex];
11417                                         VectorCopy(vertex3f + index, v[cornerindex]);
11418                                 }
11419                         }
11420                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11421                         {
11422                                 // convert vertex positions to texcoords
11423                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11424                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11425                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11426                                 // calculate distance fade from the projection origin
11427                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11428                                 f = bound(0.0f, f, 1.0f);
11429                                 c[cornerindex][0] = r * f;
11430                                 c[cornerindex][1] = g * f;
11431                                 c[cornerindex][2] = b * f;
11432                                 c[cornerindex][3] = 1.0f;
11433                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11434                         }
11435                         if (dynamic)
11436                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
11437                         else
11438                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11439                                         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);
11440                 }
11441         }
11442 }
11443
11444 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11445 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)
11446 {
11447         int renderentityindex;
11448         float worldmins[3];
11449         float worldmaxs[3];
11450         entity_render_t *ent;
11451
11452         if (!cl_decals_newsystem.integer)
11453                 return;
11454
11455         worldmins[0] = worldorigin[0] - worldsize;
11456         worldmins[1] = worldorigin[1] - worldsize;
11457         worldmins[2] = worldorigin[2] - worldsize;
11458         worldmaxs[0] = worldorigin[0] + worldsize;
11459         worldmaxs[1] = worldorigin[1] + worldsize;
11460         worldmaxs[2] = worldorigin[2] + worldsize;
11461
11462         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11463
11464         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11465         {
11466                 ent = r_refdef.scene.entities[renderentityindex];
11467                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11468                         continue;
11469
11470                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11471         }
11472 }
11473
11474 typedef struct r_decalsystem_splatqueue_s
11475 {
11476         vec3_t worldorigin;
11477         vec3_t worldnormal;
11478         float color[4];
11479         float tcrange[4];
11480         float worldsize;
11481         int decalsequence;
11482 }
11483 r_decalsystem_splatqueue_t;
11484
11485 int r_decalsystem_numqueued = 0;
11486 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11487
11488 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)
11489 {
11490         r_decalsystem_splatqueue_t *queue;
11491
11492         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11493                 return;
11494
11495         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11496         VectorCopy(worldorigin, queue->worldorigin);
11497         VectorCopy(worldnormal, queue->worldnormal);
11498         Vector4Set(queue->color, r, g, b, a);
11499         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11500         queue->worldsize = worldsize;
11501         queue->decalsequence = cl.decalsequence++;
11502 }
11503
11504 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11505 {
11506         int i;
11507         r_decalsystem_splatqueue_t *queue;
11508
11509         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11510                 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);
11511         r_decalsystem_numqueued = 0;
11512 }
11513
11514 extern cvar_t cl_decals_max;
11515 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11516 {
11517         int i;
11518         decalsystem_t *decalsystem = &ent->decalsystem;
11519         int numdecals;
11520         int killsequence;
11521         tridecal_t *decal;
11522         float frametime;
11523         float lifetime;
11524
11525         if (!decalsystem->numdecals)
11526                 return;
11527
11528         if (r_showsurfaces.integer)
11529                 return;
11530
11531         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11532         {
11533                 R_DecalSystem_Reset(decalsystem);
11534                 return;
11535         }
11536
11537         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11538         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11539
11540         if (decalsystem->lastupdatetime)
11541                 frametime = (cl.time - decalsystem->lastupdatetime);
11542         else
11543                 frametime = 0;
11544         decalsystem->lastupdatetime = cl.time;
11545         decal = decalsystem->decals;
11546         numdecals = decalsystem->numdecals;
11547
11548         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11549         {
11550                 if (decal->color4ub[0][3])
11551                 {
11552                         decal->lived += frametime;
11553                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11554                         {
11555                                 memset(decal, 0, sizeof(*decal));
11556                                 if (decalsystem->freedecal > i)
11557                                         decalsystem->freedecal = i;
11558                         }
11559                 }
11560         }
11561         decal = decalsystem->decals;
11562         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11563                 numdecals--;
11564
11565         // collapse the array by shuffling the tail decals into the gaps
11566         for (;;)
11567         {
11568                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11569                         decalsystem->freedecal++;
11570                 if (decalsystem->freedecal == numdecals)
11571                         break;
11572                 decal[decalsystem->freedecal] = decal[--numdecals];
11573         }
11574
11575         decalsystem->numdecals = numdecals;
11576
11577         if (numdecals <= 0)
11578         {
11579                 // if there are no decals left, reset decalsystem
11580                 R_DecalSystem_Reset(decalsystem);
11581         }
11582 }
11583
11584 extern skinframe_t *decalskinframe;
11585 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11586 {
11587         int i;
11588         decalsystem_t *decalsystem = &ent->decalsystem;
11589         int numdecals;
11590         tridecal_t *decal;
11591         float fadedelay;
11592         float faderate;
11593         float alpha;
11594         float *v3f;
11595         float *c4f;
11596         float *t2f;
11597         const int *e;
11598         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11599         int numtris = 0;
11600
11601         numdecals = decalsystem->numdecals;
11602         if (!numdecals)
11603                 return;
11604
11605         if (r_showsurfaces.integer)
11606                 return;
11607
11608         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11609         {
11610                 R_DecalSystem_Reset(decalsystem);
11611                 return;
11612         }
11613
11614         // if the model is static it doesn't matter what value we give for
11615         // wantnormals and wanttangents, so this logic uses only rules applicable
11616         // to a model, knowing that they are meaningless otherwise
11617         if (ent == r_refdef.scene.worldentity)
11618                 RSurf_ActiveWorldEntity();
11619         else
11620                 RSurf_ActiveModelEntity(ent, false, false, false);
11621
11622         decalsystem->lastupdatetime = cl.time;
11623         decal = decalsystem->decals;
11624
11625         fadedelay = cl_decals_time.value;
11626         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11627
11628         // update vertex positions for animated models
11629         v3f = decalsystem->vertex3f;
11630         c4f = decalsystem->color4f;
11631         t2f = decalsystem->texcoord2f;
11632         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11633         {
11634                 if (!decal->color4ub[0][3])
11635                         continue;
11636
11637                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11638                         continue;
11639
11640                 // update color values for fading decals
11641                 if (decal->lived >= cl_decals_time.value)
11642                 {
11643                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11644                         alpha *= (1.0f/255.0f);
11645                 }
11646                 else
11647                         alpha = 1.0f/255.0f;
11648
11649                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11650                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11651                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11652                 c4f[ 3] = 1;
11653                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11654                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11655                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11656                 c4f[ 7] = 1;
11657                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11658                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11659                 c4f[10] = decal->color4ub[2][2] * alpha;
11660                 c4f[11] = 1;
11661
11662                 t2f[0] = decal->texcoord2f[0][0];
11663                 t2f[1] = decal->texcoord2f[0][1];
11664                 t2f[2] = decal->texcoord2f[1][0];
11665                 t2f[3] = decal->texcoord2f[1][1];
11666                 t2f[4] = decal->texcoord2f[2][0];
11667                 t2f[5] = decal->texcoord2f[2][1];
11668
11669                 // update vertex positions for animated models
11670                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11671                 {
11672                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11673                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11674                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11675                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11676                 }
11677                 else
11678                 {
11679                         VectorCopy(decal->vertex3f[0], v3f);
11680                         VectorCopy(decal->vertex3f[1], v3f + 3);
11681                         VectorCopy(decal->vertex3f[2], v3f + 6);
11682                 }
11683
11684                 v3f += 9;
11685                 c4f += 12;
11686                 t2f += 6;
11687                 numtris++;
11688         }
11689
11690         if (numtris > 0)
11691         {
11692                 r_refdef.stats.drawndecals += numtris;
11693
11694                 if (r_refdef.fogenabled)
11695                 {
11696                         switch(vid.renderpath)
11697                         {
11698                         case RENDERPATH_GL20:
11699                         case RENDERPATH_CGGL:
11700                         case RENDERPATH_GL13:
11701                         case RENDERPATH_GL11:
11702                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11703                                 {
11704                                         alpha = RSurf_FogVertex(v3f);
11705                                         c4f[0] *= alpha;
11706                                         c4f[1] *= alpha;
11707                                         c4f[2] *= alpha;
11708                                 }
11709                                 break;
11710                         }
11711                 }
11712
11713                 // now render the decals all at once
11714                 // (this assumes they all use one particle font texture!)
11715                 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);
11716                 R_Mesh_ResetTextureState();
11717                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11718                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11719                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11720                 GL_DepthMask(false);
11721                 GL_DepthRange(0, 1);
11722                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11723                 GL_DepthTest(true);
11724                 GL_CullFace(GL_NONE);
11725                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11726                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11727                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11728         }
11729 }
11730
11731 static void R_DrawModelDecals(void)
11732 {
11733         int i, numdecals;
11734
11735         // fade faster when there are too many decals
11736         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11737         for (i = 0;i < r_refdef.scene.numentities;i++)
11738                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11739
11740         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11741         for (i = 0;i < r_refdef.scene.numentities;i++)
11742                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11743                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11744
11745         R_DecalSystem_ApplySplatEntitiesQueue();
11746
11747         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11748         for (i = 0;i < r_refdef.scene.numentities;i++)
11749                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11750
11751         r_refdef.stats.totaldecals += numdecals;
11752
11753         if (r_showsurfaces.integer)
11754                 return;
11755
11756         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11757
11758         for (i = 0;i < r_refdef.scene.numentities;i++)
11759         {
11760                 if (!r_refdef.viewcache.entityvisible[i])
11761                         continue;
11762                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11763                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11764         }
11765 }
11766
11767 void R_DrawDebugModel(void)
11768 {
11769         entity_render_t *ent = rsurface.entity;
11770         int i, j, k, l, flagsmask;
11771         const int *elements;
11772         q3mbrush_t *brush;
11773         const msurface_t *surface;
11774         dp_model_t *model = ent->model;
11775         vec3_t v;
11776
11777         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11778
11779         R_Mesh_ColorPointer(NULL, 0, 0);
11780         R_Mesh_ResetTextureState();
11781         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11782         GL_DepthRange(0, 1);
11783         GL_DepthTest(!r_showdisabledepthtest.integer);
11784         GL_DepthMask(false);
11785         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11786
11787         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11788         {
11789                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11790                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11791                 {
11792                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11793                         {
11794                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11795                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11796                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11797                         }
11798                 }
11799                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11800                 {
11801                         if (surface->num_collisiontriangles)
11802                         {
11803                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11804                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11805                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11806                         }
11807                 }
11808         }
11809
11810         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11811
11812         if (r_showtris.integer || r_shownormals.integer)
11813         {
11814                 if (r_showdisabledepthtest.integer)
11815                 {
11816                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11817                         GL_DepthMask(false);
11818                 }
11819                 else
11820                 {
11821                         GL_BlendFunc(GL_ONE, GL_ZERO);
11822                         GL_DepthMask(true);
11823                 }
11824                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11825                 {
11826                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11827                                 continue;
11828                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11829                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11830                         {
11831                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11832                                 if (r_showtris.value > 0)
11833                                 {
11834                                         if (!rsurface.texture->currentlayers->depthmask)
11835                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11836                                         else if (ent == r_refdef.scene.worldentity)
11837                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11838                                         else
11839                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11840                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11841                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11842                                         R_Mesh_ColorPointer(NULL, 0, 0);
11843                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11844                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11845                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11846                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11847                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11848                                         CHECKGLERROR
11849                                 }
11850                                 if (r_shownormals.value < 0)
11851                                 {
11852                                         qglBegin(GL_LINES);
11853                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11854                                         {
11855                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11856                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11857                                                 qglVertex3f(v[0], v[1], v[2]);
11858                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11859                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11860                                                 qglVertex3f(v[0], v[1], v[2]);
11861                                         }
11862                                         qglEnd();
11863                                         CHECKGLERROR
11864                                 }
11865                                 if (r_shownormals.value > 0)
11866                                 {
11867                                         qglBegin(GL_LINES);
11868                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11869                                         {
11870                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11871                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11872                                                 qglVertex3f(v[0], v[1], v[2]);
11873                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11874                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11875                                                 qglVertex3f(v[0], v[1], v[2]);
11876                                         }
11877                                         qglEnd();
11878                                         CHECKGLERROR
11879                                         qglBegin(GL_LINES);
11880                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11881                                         {
11882                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11883                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11884                                                 qglVertex3f(v[0], v[1], v[2]);
11885                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11886                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11887                                                 qglVertex3f(v[0], v[1], v[2]);
11888                                         }
11889                                         qglEnd();
11890                                         CHECKGLERROR
11891                                         qglBegin(GL_LINES);
11892                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11893                                         {
11894                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11895                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11896                                                 qglVertex3f(v[0], v[1], v[2]);
11897                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11898                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11899                                                 qglVertex3f(v[0], v[1], v[2]);
11900                                         }
11901                                         qglEnd();
11902                                         CHECKGLERROR
11903                                 }
11904                         }
11905                 }
11906                 rsurface.texture = NULL;
11907         }
11908 }
11909
11910 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11911 int r_maxsurfacelist = 0;
11912 const msurface_t **r_surfacelist = NULL;
11913 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11914 {
11915         int i, j, endj, f, flagsmask;
11916         texture_t *t;
11917         dp_model_t *model = r_refdef.scene.worldmodel;
11918         msurface_t *surfaces;
11919         unsigned char *update;
11920         int numsurfacelist = 0;
11921         if (model == NULL)
11922                 return;
11923
11924         if (r_maxsurfacelist < model->num_surfaces)
11925         {
11926                 r_maxsurfacelist = model->num_surfaces;
11927                 if (r_surfacelist)
11928                         Mem_Free((msurface_t**)r_surfacelist);
11929                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11930         }
11931
11932         RSurf_ActiveWorldEntity();
11933
11934         surfaces = model->data_surfaces;
11935         update = model->brushq1.lightmapupdateflags;
11936
11937         // update light styles on this submodel
11938         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11939         {
11940                 model_brush_lightstyleinfo_t *style;
11941                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11942                 {
11943                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11944                         {
11945                                 int *list = style->surfacelist;
11946                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11947                                 for (j = 0;j < style->numsurfaces;j++)
11948                                         update[list[j]] = true;
11949                         }
11950                 }
11951         }
11952
11953         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11954
11955         if (debug)
11956         {
11957                 R_DrawDebugModel();
11958                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11959                 return;
11960         }
11961
11962         f = 0;
11963         t = NULL;
11964         rsurface.uselightmaptexture = false;
11965         rsurface.texture = NULL;
11966         rsurface.rtlight = NULL;
11967         numsurfacelist = 0;
11968         // add visible surfaces to draw list
11969         for (i = 0;i < model->nummodelsurfaces;i++)
11970         {
11971                 j = model->sortedmodelsurfaces[i];
11972                 if (r_refdef.viewcache.world_surfacevisible[j])
11973                         r_surfacelist[numsurfacelist++] = surfaces + j;
11974         }
11975         // update lightmaps if needed
11976         if (model->brushq1.firstrender)
11977         {
11978                 model->brushq1.firstrender = false;
11979                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11980                         if (update[j])
11981                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11982         }
11983         else if (update)
11984         {
11985                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11986                         if (r_refdef.viewcache.world_surfacevisible[j])
11987                                 if (update[j])
11988                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11989         }
11990         // don't do anything if there were no surfaces
11991         if (!numsurfacelist)
11992         {
11993                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11994                 return;
11995         }
11996         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11997         GL_AlphaTest(false);
11998
11999         // add to stats if desired
12000         if (r_speeds.integer && !skysurfaces && !depthonly)
12001         {
12002                 r_refdef.stats.world_surfaces += numsurfacelist;
12003                 for (j = 0;j < numsurfacelist;j++)
12004                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12005         }
12006
12007         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12008 }
12009
12010 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12011 {
12012         int i, j, endj, f, flagsmask;
12013         texture_t *t;
12014         dp_model_t *model = ent->model;
12015         msurface_t *surfaces;
12016         unsigned char *update;
12017         int numsurfacelist = 0;
12018         if (model == NULL)
12019                 return;
12020
12021         if (r_maxsurfacelist < model->num_surfaces)
12022         {
12023                 r_maxsurfacelist = model->num_surfaces;
12024                 if (r_surfacelist)
12025                         Mem_Free((msurface_t **)r_surfacelist);
12026                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12027         }
12028
12029         // if the model is static it doesn't matter what value we give for
12030         // wantnormals and wanttangents, so this logic uses only rules applicable
12031         // to a model, knowing that they are meaningless otherwise
12032         if (ent == r_refdef.scene.worldentity)
12033                 RSurf_ActiveWorldEntity();
12034         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12035                 RSurf_ActiveModelEntity(ent, false, false, false);
12036         else if (prepass)
12037                 RSurf_ActiveModelEntity(ent, true, true, true);
12038         else if (depthonly)
12039                 RSurf_ActiveModelEntity(ent, false, false, false);
12040         else
12041         {
12042                 switch (vid.renderpath)
12043                 {
12044                 case RENDERPATH_GL20:
12045                 case RENDERPATH_CGGL:
12046                         RSurf_ActiveModelEntity(ent, true, true, false);
12047                         break;
12048                 case RENDERPATH_GL13:
12049                 case RENDERPATH_GL11:
12050                         RSurf_ActiveModelEntity(ent, true, false, false);
12051                         break;
12052                 }
12053         }
12054
12055         surfaces = model->data_surfaces;
12056         update = model->brushq1.lightmapupdateflags;
12057
12058         // update light styles
12059         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12060         {
12061                 model_brush_lightstyleinfo_t *style;
12062                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12063                 {
12064                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12065                         {
12066                                 int *list = style->surfacelist;
12067                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12068                                 for (j = 0;j < style->numsurfaces;j++)
12069                                         update[list[j]] = true;
12070                         }
12071                 }
12072         }
12073
12074         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12075
12076         if (debug)
12077         {
12078                 R_DrawDebugModel();
12079                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12080                 return;
12081         }
12082
12083         f = 0;
12084         t = NULL;
12085         rsurface.uselightmaptexture = false;
12086         rsurface.texture = NULL;
12087         rsurface.rtlight = NULL;
12088         numsurfacelist = 0;
12089         // add visible surfaces to draw list
12090         for (i = 0;i < model->nummodelsurfaces;i++)
12091                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12092         // don't do anything if there were no surfaces
12093         if (!numsurfacelist)
12094         {
12095                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12096                 return;
12097         }
12098         // update lightmaps if needed
12099         if (update)
12100         {
12101                 int updated = 0;
12102                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12103                 {
12104                         if (update[j])
12105                         {
12106                                 updated++;
12107                                 R_BuildLightMap(ent, surfaces + j);
12108                         }
12109                 }
12110         }
12111         if (update)
12112                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12113                         if (update[j])
12114                                 R_BuildLightMap(ent, surfaces + j);
12115         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12116         GL_AlphaTest(false);
12117
12118         // add to stats if desired
12119         if (r_speeds.integer && !skysurfaces && !depthonly)
12120         {
12121                 r_refdef.stats.entities_surfaces += numsurfacelist;
12122                 for (j = 0;j < numsurfacelist;j++)
12123                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12124         }
12125
12126         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12127 }
12128
12129 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12130 {
12131         static texture_t texture;
12132         static msurface_t surface;
12133         const msurface_t *surfacelist = &surface;
12134
12135         // fake enough texture and surface state to render this geometry
12136
12137         texture.update_lastrenderframe = -1; // regenerate this texture
12138         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12139         texture.currentskinframe = skinframe;
12140         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12141         texture.specularscalemod = 1;
12142         texture.specularpowermod = 1;
12143
12144         surface.texture = &texture;
12145         surface.num_triangles = numtriangles;
12146         surface.num_firsttriangle = firsttriangle;
12147         surface.num_vertices = numvertices;
12148         surface.num_firstvertex = firstvertex;
12149
12150         // now render it
12151         rsurface.texture = R_GetCurrentTexture(surface.texture);
12152         rsurface.uselightmaptexture = false;
12153         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12154 }
12155
12156 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)
12157 {
12158         static msurface_t surface;
12159         const msurface_t *surfacelist = &surface;
12160
12161         // fake enough texture and surface state to render this geometry
12162
12163         surface.texture = texture;
12164         surface.num_triangles = numtriangles;
12165         surface.num_firsttriangle = firsttriangle;
12166         surface.num_vertices = numvertices;
12167         surface.num_firstvertex = firstvertex;
12168
12169         // now render it
12170         rsurface.texture = R_GetCurrentTexture(surface.texture);
12171         rsurface.uselightmaptexture = false;
12172         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12173 }